diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-14 10:43:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-14 10:43:11 -0400 |
commit | a2c7a54fcc36dc3d0d461e883d9535f8f52f5a3f (patch) | |
tree | 3bc7e727e6ebe67d7099b01a1b3cc159840912ca /arch/powerpc/kernel | |
parent | 674825d05001e218afe5a04438683e1e597e14fb (diff) | |
parent | e34166ad63eac4d0fa98b4c4ed7a98202a18faef (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Benjamin Herrenschmidt:
"This is mostly bug fixes (some of them regressions, some of them I
deemed worth merging now) along with some patches from Li Zhong
hooking up the new context tracking stuff (for the new full NO_HZ)"
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (25 commits)
powerpc: Set show_unhandled_signals to 1 by default
powerpc/perf: Fix setting of "to" addresses for BHRB
powerpc/pmu: Fix order of interpreting BHRB target entries
powerpc/perf: Move BHRB code into CONFIG_PPC64 region
powerpc: select HAVE_CONTEXT_TRACKING for pSeries
powerpc: Use the new schedule_user API on userspace preemption
powerpc: Exit user context on notify resume
powerpc: Exception hooks for context tracking subsystem
powerpc: Syscall hooks for context tracking subsystem
powerpc/booke64: Fix kernel hangs at kernel_dbg_exc
powerpc: Fix irq_set_affinity() return values
powerpc: Provide __bswapdi2
powerpc/powernv: Fix starting of secondary CPUs on OPALv2 and v3
powerpc/powernv: Detect OPAL v3 API version
powerpc: Fix MAX_STACK_TRACE_ENTRIES too low warning again
powerpc: Make CONFIG_RTAS_PROC depend on CONFIG_PROC_FS
powerpc: Bring all threads online prior to migration/hibernation
powerpc/rtas_flash: Fix validate_flash buffer overflow issue
powerpc/kexec: Fix kexec when using VMX optimised memcpy
powerpc: Fix build errors STRICT_MM_TYPECHECKS
...
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_64.S | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 113 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_flash.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/signal.c | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 80 | ||||
-rw-r--r-- | arch/powerpc/kernel/udbg.c | 3 |
15 files changed, 235 insertions, 40 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index e514de57a125..d22e73e4618b 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -439,8 +439,6 @@ ret_from_fork: | |||
439 | ret_from_kernel_thread: | 439 | ret_from_kernel_thread: |
440 | REST_NVGPRS(r1) | 440 | REST_NVGPRS(r1) |
441 | bl schedule_tail | 441 | bl schedule_tail |
442 | li r3,0 | ||
443 | stw r3,0(r1) | ||
444 | mtlr r14 | 442 | mtlr r14 |
445 | mr r3,r15 | 443 | mr r3,r15 |
446 | PPC440EP_ERR42 | 444 | PPC440EP_ERR42 |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 915fbb4fc2fe..51cfb8fc301f 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/irqflags.h> | 33 | #include <asm/irqflags.h> |
34 | #include <asm/ftrace.h> | 34 | #include <asm/ftrace.h> |
35 | #include <asm/hw_irq.h> | 35 | #include <asm/hw_irq.h> |
36 | #include <asm/context_tracking.h> | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * System calls. | 39 | * System calls. |
@@ -376,8 +377,6 @@ _GLOBAL(ret_from_fork) | |||
376 | _GLOBAL(ret_from_kernel_thread) | 377 | _GLOBAL(ret_from_kernel_thread) |
377 | bl .schedule_tail | 378 | bl .schedule_tail |
378 | REST_NVGPRS(r1) | 379 | REST_NVGPRS(r1) |
379 | li r3,0 | ||
380 | std r3,0(r1) | ||
381 | ld r14, 0(r14) | 380 | ld r14, 0(r14) |
382 | mtlr r14 | 381 | mtlr r14 |
383 | mr r3,r15 | 382 | mr r3,r15 |
@@ -634,7 +633,7 @@ _GLOBAL(ret_from_except_lite) | |||
634 | andi. r0,r4,_TIF_NEED_RESCHED | 633 | andi. r0,r4,_TIF_NEED_RESCHED |
635 | beq 1f | 634 | beq 1f |
636 | bl .restore_interrupts | 635 | bl .restore_interrupts |
637 | bl .schedule | 636 | SCHEDULE_USER |
638 | b .ret_from_except_lite | 637 | b .ret_from_except_lite |
639 | 638 | ||
640 | 1: bl .save_nvgprs | 639 | 1: bl .save_nvgprs |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 42a756eec9ff..645170a07ada 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -489,7 +489,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
489 | */ | 489 | */ |
490 | 490 | ||
491 | mfspr r14,SPRN_DBSR /* check single-step/branch taken */ | 491 | mfspr r14,SPRN_DBSR /* check single-step/branch taken */ |
492 | andis. r15,r14,DBSR_IC@h | 492 | andis. r15,r14,(DBSR_IC|DBSR_BT)@h |
493 | beq+ 1f | 493 | beq+ 1f |
494 | 494 | ||
495 | LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) | 495 | LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) |
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
500 | bge+ cr1,1f | 500 | bge+ cr1,1f |
501 | 501 | ||
502 | /* here it looks like we got an inappropriate debug exception. */ | 502 | /* here it looks like we got an inappropriate debug exception. */ |
503 | lis r14,DBSR_IC@h /* clear the IC event */ | 503 | lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */ |
504 | rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */ | 504 | rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */ |
505 | mtspr SPRN_DBSR,r14 | 505 | mtspr SPRN_DBSR,r14 |
506 | mtspr SPRN_CSRR1,r11 | 506 | mtspr SPRN_CSRR1,r11 |
@@ -555,7 +555,7 @@ kernel_dbg_exc: | |||
555 | */ | 555 | */ |
556 | 556 | ||
557 | mfspr r14,SPRN_DBSR /* check single-step/branch taken */ | 557 | mfspr r14,SPRN_DBSR /* check single-step/branch taken */ |
558 | andis. r15,r14,DBSR_IC@h | 558 | andis. r15,r14,(DBSR_IC|DBSR_BT)@h |
559 | beq+ 1f | 559 | beq+ 1f |
560 | 560 | ||
561 | LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) | 561 | LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) |
@@ -566,7 +566,7 @@ kernel_dbg_exc: | |||
566 | bge+ cr1,1f | 566 | bge+ cr1,1f |
567 | 567 | ||
568 | /* here it looks like we got an inappropriate debug exception. */ | 568 | /* here it looks like we got an inappropriate debug exception. */ |
569 | lis r14,DBSR_IC@h /* clear the IC event */ | 569 | lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */ |
570 | rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */ | 570 | rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */ |
571 | mtspr SPRN_DBSR,r14 | 571 | mtspr SPRN_DBSR,r14 |
572 | mtspr SPRN_DSRR1,r11 | 572 | mtspr SPRN_DSRR1,r11 |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 466a2908bb63..611acdf30096 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/cpu.h> | 19 | #include <linux/cpu.h> |
20 | #include <linux/hardirq.h> | ||
20 | 21 | ||
21 | #include <asm/page.h> | 22 | #include <asm/page.h> |
22 | #include <asm/current.h> | 23 | #include <asm/current.h> |
@@ -335,10 +336,13 @@ void default_machine_kexec(struct kimage *image) | |||
335 | pr_debug("kexec: Starting switchover sequence.\n"); | 336 | pr_debug("kexec: Starting switchover sequence.\n"); |
336 | 337 | ||
337 | /* switch to a staticly allocated stack. Based on irq stack code. | 338 | /* switch to a staticly allocated stack. Based on irq stack code. |
339 | * We setup preempt_count to avoid using VMX in memcpy. | ||
338 | * XXX: the task struct will likely be invalid once we do the copy! | 340 | * XXX: the task struct will likely be invalid once we do the copy! |
339 | */ | 341 | */ |
340 | kexec_stack.thread_info.task = current_thread_info()->task; | 342 | kexec_stack.thread_info.task = current_thread_info()->task; |
341 | kexec_stack.thread_info.flags = 0; | 343 | kexec_stack.thread_info.flags = 0; |
344 | kexec_stack.thread_info.preempt_count = HARDIRQ_OFFSET; | ||
345 | kexec_stack.thread_info.cpu = current_thread_info()->cpu; | ||
342 | 346 | ||
343 | /* We need a static PACA, too; copy this CPU's PACA over and switch to | 347 | /* We need a static PACA, too; copy this CPU's PACA over and switch to |
344 | * it. Also poison per_cpu_offset to catch anyone using non-static | 348 | * it. Also poison per_cpu_offset to catch anyone using non-static |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 19e096bd0e73..e469f30e6eeb 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -657,6 +657,17 @@ _GLOBAL(__ucmpdi2) | |||
657 | li r3,2 | 657 | li r3,2 |
658 | blr | 658 | blr |
659 | 659 | ||
660 | _GLOBAL(__bswapdi2) | ||
661 | rotlwi r9,r4,8 | ||
662 | rotlwi r10,r3,8 | ||
663 | rlwimi r9,r4,24,0,7 | ||
664 | rlwimi r10,r3,24,0,7 | ||
665 | rlwimi r9,r4,24,16,23 | ||
666 | rlwimi r10,r3,24,16,23 | ||
667 | mr r3,r9 | ||
668 | mr r4,r10 | ||
669 | blr | ||
670 | |||
660 | _GLOBAL(abs) | 671 | _GLOBAL(abs) |
661 | srawi r4,r3,31 | 672 | srawi r4,r3,31 |
662 | xor r3,r3,r4 | 673 | xor r3,r3,r4 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 5cfa8008693b..6820e45f557b 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -234,6 +234,17 @@ _GLOBAL(__flush_dcache_icache) | |||
234 | isync | 234 | isync |
235 | blr | 235 | blr |
236 | 236 | ||
237 | _GLOBAL(__bswapdi2) | ||
238 | srdi r8,r3,32 | ||
239 | rlwinm r7,r3,8,0xffffffff | ||
240 | rlwimi r7,r3,24,0,7 | ||
241 | rlwinm r9,r8,8,0xffffffff | ||
242 | rlwimi r7,r3,24,16,23 | ||
243 | rlwimi r9,r8,24,0,7 | ||
244 | rlwimi r9,r8,24,16,23 | ||
245 | sldi r7,r7,32 | ||
246 | or r3,r7,r9 | ||
247 | blr | ||
237 | 248 | ||
238 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) | 249 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) |
239 | /* | 250 | /* |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f5c5c90799a7..6053f037ef0a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -359,7 +359,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
359 | enum pci_mmap_state mmap_state, | 359 | enum pci_mmap_state mmap_state, |
360 | int write_combine) | 360 | int write_combine) |
361 | { | 361 | { |
362 | unsigned long prot = pgprot_val(protection); | ||
363 | 362 | ||
364 | /* Write combine is always 0 on non-memory space mappings. On | 363 | /* Write combine is always 0 on non-memory space mappings. On |
365 | * memory space, if the user didn't pass 1, we check for a | 364 | * memory space, if the user didn't pass 1, we check for a |
@@ -376,9 +375,9 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
376 | 375 | ||
377 | /* XXX would be nice to have a way to ask for write-through */ | 376 | /* XXX would be nice to have a way to ask for write-through */ |
378 | if (write_combine) | 377 | if (write_combine) |
379 | return pgprot_noncached_wc(prot); | 378 | return pgprot_noncached_wc(protection); |
380 | else | 379 | else |
381 | return pgprot_noncached(prot); | 380 | return pgprot_noncached(protection); |
382 | } | 381 | } |
383 | 382 | ||
384 | /* | 383 | /* |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 78b8766fd79e..c29666586998 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -143,7 +143,8 @@ EXPORT_SYMBOL(__lshrdi3); | |||
143 | int __ucmpdi2(unsigned long long, unsigned long long); | 143 | int __ucmpdi2(unsigned long long, unsigned long long); |
144 | EXPORT_SYMBOL(__ucmpdi2); | 144 | EXPORT_SYMBOL(__ucmpdi2); |
145 | #endif | 145 | #endif |
146 | 146 | long long __bswapdi2(long long); | |
147 | EXPORT_SYMBOL(__bswapdi2); | ||
147 | EXPORT_SYMBOL(memcpy); | 148 | EXPORT_SYMBOL(memcpy); |
148 | EXPORT_SYMBOL(memset); | 149 | EXPORT_SYMBOL(memset); |
149 | EXPORT_SYMBOL(memmove); | 150 | EXPORT_SYMBOL(memmove); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ceb4e7b62cf4..a902723fdc69 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -339,6 +339,13 @@ static void set_debug_reg_defaults(struct thread_struct *thread) | |||
339 | 339 | ||
340 | static void prime_debug_regs(struct thread_struct *thread) | 340 | static void prime_debug_regs(struct thread_struct *thread) |
341 | { | 341 | { |
342 | /* | ||
343 | * We could have inherited MSR_DE from userspace, since | ||
344 | * it doesn't get cleared on exception entry. Make sure | ||
345 | * MSR_DE is clear before we enable any debug events. | ||
346 | */ | ||
347 | mtmsr(mfmsr() & ~MSR_DE); | ||
348 | |||
342 | mtspr(SPRN_IAC1, thread->iac1); | 349 | mtspr(SPRN_IAC1, thread->iac1); |
343 | mtspr(SPRN_IAC2, thread->iac2); | 350 | mtspr(SPRN_IAC2, thread->iac2); |
344 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 351 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
@@ -971,6 +978,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
971 | * do some house keeping and then return from the fork or clone | 978 | * do some house keeping and then return from the fork or clone |
972 | * system call, using the stack frame created above. | 979 | * system call, using the stack frame created above. |
973 | */ | 980 | */ |
981 | ((unsigned long *)sp)[0] = 0; | ||
974 | sp -= sizeof(struct pt_regs); | 982 | sp -= sizeof(struct pt_regs); |
975 | kregs = (struct pt_regs *) sp; | 983 | kregs = (struct pt_regs *) sp; |
976 | sp -= STACK_FRAME_OVERHEAD; | 984 | sp -= STACK_FRAME_OVERHEAD; |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 3b14d320e69f..98c2fc198712 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <trace/syscall.h> | 32 | #include <trace/syscall.h> |
33 | #include <linux/hw_breakpoint.h> | 33 | #include <linux/hw_breakpoint.h> |
34 | #include <linux/perf_event.h> | 34 | #include <linux/perf_event.h> |
35 | #include <linux/context_tracking.h> | ||
35 | 36 | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <asm/page.h> | 38 | #include <asm/page.h> |
@@ -1788,6 +1789,8 @@ long do_syscall_trace_enter(struct pt_regs *regs) | |||
1788 | { | 1789 | { |
1789 | long ret = 0; | 1790 | long ret = 0; |
1790 | 1791 | ||
1792 | user_exit(); | ||
1793 | |||
1791 | secure_computing_strict(regs->gpr[0]); | 1794 | secure_computing_strict(regs->gpr[0]); |
1792 | 1795 | ||
1793 | if (test_thread_flag(TIF_SYSCALL_TRACE) && | 1796 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
@@ -1832,4 +1835,6 @@ void do_syscall_trace_leave(struct pt_regs *regs) | |||
1832 | step = test_thread_flag(TIF_SINGLESTEP); | 1835 | step = test_thread_flag(TIF_SINGLESTEP); |
1833 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) | 1836 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
1834 | tracehook_report_syscall_exit(regs, step); | 1837 | tracehook_report_syscall_exit(regs, step); |
1838 | |||
1839 | user_enter(); | ||
1835 | } | 1840 | } |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 1fd6e7b2f390..52add6f3e201 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/capability.h> | 20 | #include <linux/capability.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/cpu.h> | ||
22 | #include <linux/smp.h> | 23 | #include <linux/smp.h> |
23 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
24 | #include <linux/cpumask.h> | 25 | #include <linux/cpumask.h> |
@@ -807,6 +808,95 @@ static void rtas_percpu_suspend_me(void *info) | |||
807 | __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); | 808 | __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); |
808 | } | 809 | } |
809 | 810 | ||
811 | enum rtas_cpu_state { | ||
812 | DOWN, | ||
813 | UP, | ||
814 | }; | ||
815 | |||
816 | #ifndef CONFIG_SMP | ||
817 | static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, | ||
818 | cpumask_var_t cpus) | ||
819 | { | ||
820 | if (!cpumask_empty(cpus)) { | ||
821 | cpumask_clear(cpus); | ||
822 | return -EINVAL; | ||
823 | } else | ||
824 | return 0; | ||
825 | } | ||
826 | #else | ||
827 | /* On return cpumask will be altered to indicate CPUs changed. | ||
828 | * CPUs with states changed will be set in the mask, | ||
829 | * CPUs with status unchanged will be unset in the mask. */ | ||
830 | static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, | ||
831 | cpumask_var_t cpus) | ||
832 | { | ||
833 | int cpu; | ||
834 | int cpuret = 0; | ||
835 | int ret = 0; | ||
836 | |||
837 | if (cpumask_empty(cpus)) | ||
838 | return 0; | ||
839 | |||
840 | for_each_cpu(cpu, cpus) { | ||
841 | switch (state) { | ||
842 | case DOWN: | ||
843 | cpuret = cpu_down(cpu); | ||
844 | break; | ||
845 | case UP: | ||
846 | cpuret = cpu_up(cpu); | ||
847 | break; | ||
848 | } | ||
849 | if (cpuret) { | ||
850 | pr_debug("%s: cpu_%s for cpu#%d returned %d.\n", | ||
851 | __func__, | ||
852 | ((state == UP) ? "up" : "down"), | ||
853 | cpu, cpuret); | ||
854 | if (!ret) | ||
855 | ret = cpuret; | ||
856 | if (state == UP) { | ||
857 | /* clear bits for unchanged cpus, return */ | ||
858 | cpumask_shift_right(cpus, cpus, cpu); | ||
859 | cpumask_shift_left(cpus, cpus, cpu); | ||
860 | break; | ||
861 | } else { | ||
862 | /* clear bit for unchanged cpu, continue */ | ||
863 | cpumask_clear_cpu(cpu, cpus); | ||
864 | } | ||
865 | } | ||
866 | } | ||
867 | |||
868 | return ret; | ||
869 | } | ||
870 | #endif | ||
871 | |||
872 | int rtas_online_cpus_mask(cpumask_var_t cpus) | ||
873 | { | ||
874 | int ret; | ||
875 | |||
876 | ret = rtas_cpu_state_change_mask(UP, cpus); | ||
877 | |||
878 | if (ret) { | ||
879 | cpumask_var_t tmp_mask; | ||
880 | |||
881 | if (!alloc_cpumask_var(&tmp_mask, GFP_TEMPORARY)) | ||
882 | return ret; | ||
883 | |||
884 | /* Use tmp_mask to preserve cpus mask from first failure */ | ||
885 | cpumask_copy(tmp_mask, cpus); | ||
886 | rtas_offline_cpus_mask(tmp_mask); | ||
887 | free_cpumask_var(tmp_mask); | ||
888 | } | ||
889 | |||
890 | return ret; | ||
891 | } | ||
892 | EXPORT_SYMBOL(rtas_online_cpus_mask); | ||
893 | |||
894 | int rtas_offline_cpus_mask(cpumask_var_t cpus) | ||
895 | { | ||
896 | return rtas_cpu_state_change_mask(DOWN, cpus); | ||
897 | } | ||
898 | EXPORT_SYMBOL(rtas_offline_cpus_mask); | ||
899 | |||
810 | int rtas_ibm_suspend_me(struct rtas_args *args) | 900 | int rtas_ibm_suspend_me(struct rtas_args *args) |
811 | { | 901 | { |
812 | long state; | 902 | long state; |
@@ -814,6 +904,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args) | |||
814 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 904 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
815 | struct rtas_suspend_me_data data; | 905 | struct rtas_suspend_me_data data; |
816 | DECLARE_COMPLETION_ONSTACK(done); | 906 | DECLARE_COMPLETION_ONSTACK(done); |
907 | cpumask_var_t offline_mask; | ||
908 | int cpuret; | ||
817 | 909 | ||
818 | if (!rtas_service_present("ibm,suspend-me")) | 910 | if (!rtas_service_present("ibm,suspend-me")) |
819 | return -ENOSYS; | 911 | return -ENOSYS; |
@@ -837,11 +929,24 @@ int rtas_ibm_suspend_me(struct rtas_args *args) | |||
837 | return 0; | 929 | return 0; |
838 | } | 930 | } |
839 | 931 | ||
932 | if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) | ||
933 | return -ENOMEM; | ||
934 | |||
840 | atomic_set(&data.working, 0); | 935 | atomic_set(&data.working, 0); |
841 | atomic_set(&data.done, 0); | 936 | atomic_set(&data.done, 0); |
842 | atomic_set(&data.error, 0); | 937 | atomic_set(&data.error, 0); |
843 | data.token = rtas_token("ibm,suspend-me"); | 938 | data.token = rtas_token("ibm,suspend-me"); |
844 | data.complete = &done; | 939 | data.complete = &done; |
940 | |||
941 | /* All present CPUs must be online */ | ||
942 | cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask); | ||
943 | cpuret = rtas_online_cpus_mask(offline_mask); | ||
944 | if (cpuret) { | ||
945 | pr_err("%s: Could not bring present CPUs online.\n", __func__); | ||
946 | atomic_set(&data.error, cpuret); | ||
947 | goto out; | ||
948 | } | ||
949 | |||
845 | stop_topology_update(); | 950 | stop_topology_update(); |
846 | 951 | ||
847 | /* Call function on all CPUs. One of us will make the | 952 | /* Call function on all CPUs. One of us will make the |
@@ -857,6 +962,14 @@ int rtas_ibm_suspend_me(struct rtas_args *args) | |||
857 | 962 | ||
858 | start_topology_update(); | 963 | start_topology_update(); |
859 | 964 | ||
965 | /* Take down CPUs not online prior to suspend */ | ||
966 | cpuret = rtas_offline_cpus_mask(offline_mask); | ||
967 | if (cpuret) | ||
968 | pr_warn("%s: Could not restore CPUs to offline state.\n", | ||
969 | __func__); | ||
970 | |||
971 | out: | ||
972 | free_cpumask_var(offline_mask); | ||
860 | return atomic_read(&data.error); | 973 | return atomic_read(&data.error); |
861 | } | 974 | } |
862 | #else /* CONFIG_PPC_PSERIES */ | 975 | #else /* CONFIG_PPC_PSERIES */ |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 5b3022470126..2f3cdb01506d 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -89,6 +89,7 @@ | |||
89 | 89 | ||
90 | /* Array sizes */ | 90 | /* Array sizes */ |
91 | #define VALIDATE_BUF_SIZE 4096 | 91 | #define VALIDATE_BUF_SIZE 4096 |
92 | #define VALIDATE_MSG_LEN 256 | ||
92 | #define RTAS_MSG_MAXLEN 64 | 93 | #define RTAS_MSG_MAXLEN 64 |
93 | 94 | ||
94 | /* Quirk - RTAS requires 4k list length and block size */ | 95 | /* Quirk - RTAS requires 4k list length and block size */ |
@@ -466,7 +467,7 @@ static void validate_flash(struct rtas_validate_flash_t *args_buf) | |||
466 | } | 467 | } |
467 | 468 | ||
468 | static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, | 469 | static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, |
469 | char *msg) | 470 | char *msg, int msglen) |
470 | { | 471 | { |
471 | int n; | 472 | int n; |
472 | 473 | ||
@@ -474,7 +475,8 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, | |||
474 | n = sprintf(msg, "%d\n", args_buf->update_results); | 475 | n = sprintf(msg, "%d\n", args_buf->update_results); |
475 | if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || | 476 | if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || |
476 | (args_buf->update_results == VALIDATE_TMP_UPDATE)) | 477 | (args_buf->update_results == VALIDATE_TMP_UPDATE)) |
477 | n += sprintf(msg + n, "%s\n", args_buf->buf); | 478 | n += snprintf(msg + n, msglen - n, "%s\n", |
479 | args_buf->buf); | ||
478 | } else { | 480 | } else { |
479 | n = sprintf(msg, "%d\n", args_buf->status); | 481 | n = sprintf(msg, "%d\n", args_buf->status); |
480 | } | 482 | } |
@@ -486,11 +488,11 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf, | |||
486 | { | 488 | { |
487 | struct rtas_validate_flash_t *const args_buf = | 489 | struct rtas_validate_flash_t *const args_buf = |
488 | &rtas_validate_flash_data; | 490 | &rtas_validate_flash_data; |
489 | char msg[RTAS_MSG_MAXLEN]; | 491 | char msg[VALIDATE_MSG_LEN]; |
490 | int msglen; | 492 | int msglen; |
491 | 493 | ||
492 | mutex_lock(&rtas_validate_flash_mutex); | 494 | mutex_lock(&rtas_validate_flash_mutex); |
493 | msglen = get_validate_flash_msg(args_buf, msg); | 495 | msglen = get_validate_flash_msg(args_buf, msg, VALIDATE_MSG_LEN); |
494 | mutex_unlock(&rtas_validate_flash_mutex); | 496 | mutex_unlock(&rtas_validate_flash_mutex); |
495 | 497 | ||
496 | return simple_read_from_buffer(buf, count, ppos, msg, msglen); | 498 | return simple_read_from_buffer(buf, count, ppos, msg, msglen); |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index cf12eae02de5..577a8aa69c6e 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/signal.h> | 13 | #include <linux/signal.h> |
14 | #include <linux/uprobes.h> | 14 | #include <linux/uprobes.h> |
15 | #include <linux/key.h> | 15 | #include <linux/key.h> |
16 | #include <linux/context_tracking.h> | ||
16 | #include <asm/hw_breakpoint.h> | 17 | #include <asm/hw_breakpoint.h> |
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
18 | #include <asm/unistd.h> | 19 | #include <asm/unistd.h> |
@@ -24,7 +25,7 @@ | |||
24 | * through debug.exception-trace sysctl. | 25 | * through debug.exception-trace sysctl. |
25 | */ | 26 | */ |
26 | 27 | ||
27 | int show_unhandled_signals = 0; | 28 | int show_unhandled_signals = 1; |
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Allocate space for the signal frame | 31 | * Allocate space for the signal frame |
@@ -159,6 +160,8 @@ static int do_signal(struct pt_regs *regs) | |||
159 | 160 | ||
160 | void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 161 | void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
161 | { | 162 | { |
163 | user_exit(); | ||
164 | |||
162 | if (thread_info_flags & _TIF_UPROBE) | 165 | if (thread_info_flags & _TIF_UPROBE) |
163 | uprobe_notify_resume(regs); | 166 | uprobe_notify_resume(regs); |
164 | 167 | ||
@@ -169,4 +172,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
169 | clear_thread_flag(TIF_NOTIFY_RESUME); | 172 | clear_thread_flag(TIF_NOTIFY_RESUME); |
170 | tracehook_notify_resume(regs); | 173 | tracehook_notify_resume(regs); |
171 | } | 174 | } |
175 | |||
176 | user_enter(); | ||
172 | } | 177 | } |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 83efa2f7d926..a7a648f6b750 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/kdebug.h> | 35 | #include <linux/kdebug.h> |
36 | #include <linux/debugfs.h> | 36 | #include <linux/debugfs.h> |
37 | #include <linux/ratelimit.h> | 37 | #include <linux/ratelimit.h> |
38 | #include <linux/context_tracking.h> | ||
38 | 39 | ||
39 | #include <asm/emulated_ops.h> | 40 | #include <asm/emulated_ops.h> |
40 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
@@ -667,6 +668,7 @@ int machine_check_generic(struct pt_regs *regs) | |||
667 | 668 | ||
668 | void machine_check_exception(struct pt_regs *regs) | 669 | void machine_check_exception(struct pt_regs *regs) |
669 | { | 670 | { |
671 | enum ctx_state prev_state = exception_enter(); | ||
670 | int recover = 0; | 672 | int recover = 0; |
671 | 673 | ||
672 | __get_cpu_var(irq_stat).mce_exceptions++; | 674 | __get_cpu_var(irq_stat).mce_exceptions++; |
@@ -683,7 +685,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
683 | recover = cur_cpu_spec->machine_check(regs); | 685 | recover = cur_cpu_spec->machine_check(regs); |
684 | 686 | ||
685 | if (recover > 0) | 687 | if (recover > 0) |
686 | return; | 688 | goto bail; |
687 | 689 | ||
688 | #if defined(CONFIG_8xx) && defined(CONFIG_PCI) | 690 | #if defined(CONFIG_8xx) && defined(CONFIG_PCI) |
689 | /* the qspan pci read routines can cause machine checks -- Cort | 691 | /* the qspan pci read routines can cause machine checks -- Cort |
@@ -693,20 +695,23 @@ void machine_check_exception(struct pt_regs *regs) | |||
693 | * -- BenH | 695 | * -- BenH |
694 | */ | 696 | */ |
695 | bad_page_fault(regs, regs->dar, SIGBUS); | 697 | bad_page_fault(regs, regs->dar, SIGBUS); |
696 | return; | 698 | goto bail; |
697 | #endif | 699 | #endif |
698 | 700 | ||
699 | if (debugger_fault_handler(regs)) | 701 | if (debugger_fault_handler(regs)) |
700 | return; | 702 | goto bail; |
701 | 703 | ||
702 | if (check_io_access(regs)) | 704 | if (check_io_access(regs)) |
703 | return; | 705 | goto bail; |
704 | 706 | ||
705 | die("Machine check", regs, SIGBUS); | 707 | die("Machine check", regs, SIGBUS); |
706 | 708 | ||
707 | /* Must die if the interrupt is not recoverable */ | 709 | /* Must die if the interrupt is not recoverable */ |
708 | if (!(regs->msr & MSR_RI)) | 710 | if (!(regs->msr & MSR_RI)) |
709 | panic("Unrecoverable Machine check"); | 711 | panic("Unrecoverable Machine check"); |
712 | |||
713 | bail: | ||
714 | exception_exit(prev_state); | ||
710 | } | 715 | } |
711 | 716 | ||
712 | void SMIException(struct pt_regs *regs) | 717 | void SMIException(struct pt_regs *regs) |
@@ -716,20 +721,29 @@ void SMIException(struct pt_regs *regs) | |||
716 | 721 | ||
717 | void unknown_exception(struct pt_regs *regs) | 722 | void unknown_exception(struct pt_regs *regs) |
718 | { | 723 | { |
724 | enum ctx_state prev_state = exception_enter(); | ||
725 | |||
719 | printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", | 726 | printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", |
720 | regs->nip, regs->msr, regs->trap); | 727 | regs->nip, regs->msr, regs->trap); |
721 | 728 | ||
722 | _exception(SIGTRAP, regs, 0, 0); | 729 | _exception(SIGTRAP, regs, 0, 0); |
730 | |||
731 | exception_exit(prev_state); | ||
723 | } | 732 | } |
724 | 733 | ||
725 | void instruction_breakpoint_exception(struct pt_regs *regs) | 734 | void instruction_breakpoint_exception(struct pt_regs *regs) |
726 | { | 735 | { |
736 | enum ctx_state prev_state = exception_enter(); | ||
737 | |||
727 | if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5, | 738 | if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5, |
728 | 5, SIGTRAP) == NOTIFY_STOP) | 739 | 5, SIGTRAP) == NOTIFY_STOP) |
729 | return; | 740 | goto bail; |
730 | if (debugger_iabr_match(regs)) | 741 | if (debugger_iabr_match(regs)) |
731 | return; | 742 | goto bail; |
732 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 743 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
744 | |||
745 | bail: | ||
746 | exception_exit(prev_state); | ||
733 | } | 747 | } |
734 | 748 | ||
735 | void RunModeException(struct pt_regs *regs) | 749 | void RunModeException(struct pt_regs *regs) |
@@ -739,15 +753,20 @@ void RunModeException(struct pt_regs *regs) | |||
739 | 753 | ||
740 | void __kprobes single_step_exception(struct pt_regs *regs) | 754 | void __kprobes single_step_exception(struct pt_regs *regs) |
741 | { | 755 | { |
756 | enum ctx_state prev_state = exception_enter(); | ||
757 | |||
742 | clear_single_step(regs); | 758 | clear_single_step(regs); |
743 | 759 | ||
744 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, | 760 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, |
745 | 5, SIGTRAP) == NOTIFY_STOP) | 761 | 5, SIGTRAP) == NOTIFY_STOP) |
746 | return; | 762 | goto bail; |
747 | if (debugger_sstep(regs)) | 763 | if (debugger_sstep(regs)) |
748 | return; | 764 | goto bail; |
749 | 765 | ||
750 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | 766 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
767 | |||
768 | bail: | ||
769 | exception_exit(prev_state); | ||
751 | } | 770 | } |
752 | 771 | ||
753 | /* | 772 | /* |
@@ -1005,6 +1024,7 @@ int is_valid_bugaddr(unsigned long addr) | |||
1005 | 1024 | ||
1006 | void __kprobes program_check_exception(struct pt_regs *regs) | 1025 | void __kprobes program_check_exception(struct pt_regs *regs) |
1007 | { | 1026 | { |
1027 | enum ctx_state prev_state = exception_enter(); | ||
1008 | unsigned int reason = get_reason(regs); | 1028 | unsigned int reason = get_reason(regs); |
1009 | extern int do_mathemu(struct pt_regs *regs); | 1029 | extern int do_mathemu(struct pt_regs *regs); |
1010 | 1030 | ||
@@ -1014,26 +1034,26 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1014 | if (reason & REASON_FP) { | 1034 | if (reason & REASON_FP) { |
1015 | /* IEEE FP exception */ | 1035 | /* IEEE FP exception */ |
1016 | parse_fpe(regs); | 1036 | parse_fpe(regs); |
1017 | return; | 1037 | goto bail; |
1018 | } | 1038 | } |
1019 | if (reason & REASON_TRAP) { | 1039 | if (reason & REASON_TRAP) { |
1020 | /* Debugger is first in line to stop recursive faults in | 1040 | /* Debugger is first in line to stop recursive faults in |
1021 | * rcu_lock, notify_die, or atomic_notifier_call_chain */ | 1041 | * rcu_lock, notify_die, or atomic_notifier_call_chain */ |
1022 | if (debugger_bpt(regs)) | 1042 | if (debugger_bpt(regs)) |
1023 | return; | 1043 | goto bail; |
1024 | 1044 | ||
1025 | /* trap exception */ | 1045 | /* trap exception */ |
1026 | if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) | 1046 | if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) |
1027 | == NOTIFY_STOP) | 1047 | == NOTIFY_STOP) |
1028 | return; | 1048 | goto bail; |
1029 | 1049 | ||
1030 | if (!(regs->msr & MSR_PR) && /* not user-mode */ | 1050 | if (!(regs->msr & MSR_PR) && /* not user-mode */ |
1031 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { | 1051 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { |
1032 | regs->nip += 4; | 1052 | regs->nip += 4; |
1033 | return; | 1053 | goto bail; |
1034 | } | 1054 | } |
1035 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 1055 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
1036 | return; | 1056 | goto bail; |
1037 | } | 1057 | } |
1038 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1058 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1039 | if (reason & REASON_TM) { | 1059 | if (reason & REASON_TM) { |
@@ -1049,7 +1069,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1049 | if (!user_mode(regs) && | 1069 | if (!user_mode(regs) && |
1050 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { | 1070 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { |
1051 | regs->nip += 4; | 1071 | regs->nip += 4; |
1052 | return; | 1072 | goto bail; |
1053 | } | 1073 | } |
1054 | /* If usermode caused this, it's done something illegal and | 1074 | /* If usermode caused this, it's done something illegal and |
1055 | * gets a SIGILL slap on the wrist. We call it an illegal | 1075 | * gets a SIGILL slap on the wrist. We call it an illegal |
@@ -1059,7 +1079,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1059 | */ | 1079 | */ |
1060 | if (user_mode(regs)) { | 1080 | if (user_mode(regs)) { |
1061 | _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); | 1081 | _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); |
1062 | return; | 1082 | goto bail; |
1063 | } else { | 1083 | } else { |
1064 | printk(KERN_EMERG "Unexpected TM Bad Thing exception " | 1084 | printk(KERN_EMERG "Unexpected TM Bad Thing exception " |
1065 | "at %lx (msr 0x%x)\n", regs->nip, reason); | 1085 | "at %lx (msr 0x%x)\n", regs->nip, reason); |
@@ -1083,16 +1103,16 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1083 | switch (do_mathemu(regs)) { | 1103 | switch (do_mathemu(regs)) { |
1084 | case 0: | 1104 | case 0: |
1085 | emulate_single_step(regs); | 1105 | emulate_single_step(regs); |
1086 | return; | 1106 | goto bail; |
1087 | case 1: { | 1107 | case 1: { |
1088 | int code = 0; | 1108 | int code = 0; |
1089 | code = __parse_fpscr(current->thread.fpscr.val); | 1109 | code = __parse_fpscr(current->thread.fpscr.val); |
1090 | _exception(SIGFPE, regs, code, regs->nip); | 1110 | _exception(SIGFPE, regs, code, regs->nip); |
1091 | return; | 1111 | goto bail; |
1092 | } | 1112 | } |
1093 | case -EFAULT: | 1113 | case -EFAULT: |
1094 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); | 1114 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); |
1095 | return; | 1115 | goto bail; |
1096 | } | 1116 | } |
1097 | /* fall through on any other errors */ | 1117 | /* fall through on any other errors */ |
1098 | #endif /* CONFIG_MATH_EMULATION */ | 1118 | #endif /* CONFIG_MATH_EMULATION */ |
@@ -1103,10 +1123,10 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1103 | case 0: | 1123 | case 0: |
1104 | regs->nip += 4; | 1124 | regs->nip += 4; |
1105 | emulate_single_step(regs); | 1125 | emulate_single_step(regs); |
1106 | return; | 1126 | goto bail; |
1107 | case -EFAULT: | 1127 | case -EFAULT: |
1108 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); | 1128 | _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); |
1109 | return; | 1129 | goto bail; |
1110 | } | 1130 | } |
1111 | } | 1131 | } |
1112 | 1132 | ||
@@ -1114,10 +1134,14 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1114 | _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); | 1134 | _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); |
1115 | else | 1135 | else |
1116 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | 1136 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); |
1137 | |||
1138 | bail: | ||
1139 | exception_exit(prev_state); | ||
1117 | } | 1140 | } |
1118 | 1141 | ||
1119 | void alignment_exception(struct pt_regs *regs) | 1142 | void alignment_exception(struct pt_regs *regs) |
1120 | { | 1143 | { |
1144 | enum ctx_state prev_state = exception_enter(); | ||
1121 | int sig, code, fixed = 0; | 1145 | int sig, code, fixed = 0; |
1122 | 1146 | ||
1123 | /* We restore the interrupt state now */ | 1147 | /* We restore the interrupt state now */ |
@@ -1131,7 +1155,7 @@ void alignment_exception(struct pt_regs *regs) | |||
1131 | if (fixed == 1) { | 1155 | if (fixed == 1) { |
1132 | regs->nip += 4; /* skip over emulated instruction */ | 1156 | regs->nip += 4; /* skip over emulated instruction */ |
1133 | emulate_single_step(regs); | 1157 | emulate_single_step(regs); |
1134 | return; | 1158 | goto bail; |
1135 | } | 1159 | } |
1136 | 1160 | ||
1137 | /* Operand address was bad */ | 1161 | /* Operand address was bad */ |
@@ -1146,6 +1170,9 @@ void alignment_exception(struct pt_regs *regs) | |||
1146 | _exception(sig, regs, code, regs->dar); | 1170 | _exception(sig, regs, code, regs->dar); |
1147 | else | 1171 | else |
1148 | bad_page_fault(regs, regs->dar, sig); | 1172 | bad_page_fault(regs, regs->dar, sig); |
1173 | |||
1174 | bail: | ||
1175 | exception_exit(prev_state); | ||
1149 | } | 1176 | } |
1150 | 1177 | ||
1151 | void StackOverflow(struct pt_regs *regs) | 1178 | void StackOverflow(struct pt_regs *regs) |
@@ -1174,23 +1201,32 @@ void trace_syscall(struct pt_regs *regs) | |||
1174 | 1201 | ||
1175 | void kernel_fp_unavailable_exception(struct pt_regs *regs) | 1202 | void kernel_fp_unavailable_exception(struct pt_regs *regs) |
1176 | { | 1203 | { |
1204 | enum ctx_state prev_state = exception_enter(); | ||
1205 | |||
1177 | printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " | 1206 | printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " |
1178 | "%lx at %lx\n", regs->trap, regs->nip); | 1207 | "%lx at %lx\n", regs->trap, regs->nip); |
1179 | die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); | 1208 | die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); |
1209 | |||
1210 | exception_exit(prev_state); | ||
1180 | } | 1211 | } |
1181 | 1212 | ||
1182 | void altivec_unavailable_exception(struct pt_regs *regs) | 1213 | void altivec_unavailable_exception(struct pt_regs *regs) |
1183 | { | 1214 | { |
1215 | enum ctx_state prev_state = exception_enter(); | ||
1216 | |||
1184 | if (user_mode(regs)) { | 1217 | if (user_mode(regs)) { |
1185 | /* A user program has executed an altivec instruction, | 1218 | /* A user program has executed an altivec instruction, |
1186 | but this kernel doesn't support altivec. */ | 1219 | but this kernel doesn't support altivec. */ |
1187 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | 1220 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); |
1188 | return; | 1221 | goto bail; |
1189 | } | 1222 | } |
1190 | 1223 | ||
1191 | printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " | 1224 | printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " |
1192 | "%lx at %lx\n", regs->trap, regs->nip); | 1225 | "%lx at %lx\n", regs->trap, regs->nip); |
1193 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); | 1226 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); |
1227 | |||
1228 | bail: | ||
1229 | exception_exit(prev_state); | ||
1194 | } | 1230 | } |
1195 | 1231 | ||
1196 | void vsx_unavailable_exception(struct pt_regs *regs) | 1232 | void vsx_unavailable_exception(struct pt_regs *regs) |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 13b867093499..9d3fdcd66290 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -64,6 +64,9 @@ void __init udbg_early_init(void) | |||
64 | udbg_init_usbgecko(); | 64 | udbg_init_usbgecko(); |
65 | #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) | 65 | #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) |
66 | udbg_init_wsp(); | 66 | udbg_init_wsp(); |
67 | #elif defined(CONFIG_PPC_EARLY_DEBUG_MEMCONS) | ||
68 | /* In memory console */ | ||
69 | udbg_init_memcons(); | ||
67 | #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) | 70 | #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) |
68 | udbg_init_ehv_bc(); | 71 | udbg_init_ehv_bc(); |
69 | #elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC) | 72 | #elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC) |