diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-13 23:48:25 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-13 23:48:25 -0400 |
| commit | 0ff8285075a1242dbc969b6b4b1719d692931a02 (patch) | |
| tree | 75498fec971960aa9a038846cf7d2561a49bce73 | |
| parent | 8d0968abd03ec6b407df117adc773562386702fa (diff) | |
| parent | 6f63e781eaf6a741fc65f773017154b20ed4ce3b (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Handle stack trace attempts before irqstacks are setup.
sparc64: Implement IRQ stacks.
sparc: remove include of linux/of_device.h from asm/of_device.h
sparc64: Fix recursion in stack overflow detection handling.
sparc/drivers: use linux/of_device.h instead of asm/of_device.h
sparc64: Don't MAGIC_SYSRQ ifdef smp_fetch_global_regs and support code.
| -rw-r--r-- | arch/sparc/include/asm/irq_64.h | 4 | ||||
| -rw-r--r-- | arch/sparc/include/asm/of_device.h | 3 | ||||
| -rw-r--r-- | arch/sparc64/kernel/irq.c | 52 | ||||
| -rw-r--r-- | arch/sparc64/kernel/kstack.h | 60 | ||||
| -rw-r--r-- | arch/sparc64/kernel/process.c | 27 | ||||
| -rw-r--r-- | arch/sparc64/kernel/smp.c | 4 | ||||
| -rw-r--r-- | arch/sparc64/kernel/stacktrace.c | 13 | ||||
| -rw-r--r-- | arch/sparc64/kernel/traps.c | 7 | ||||
| -rw-r--r-- | arch/sparc64/lib/mcount.S | 39 | ||||
| -rw-r--r-- | arch/sparc64/mm/init.c | 11 | ||||
| -rw-r--r-- | arch/sparc64/mm/ultra.S | 2 | ||||
| -rw-r--r-- | drivers/input/serio/i8042-sparcio.h | 3 | ||||
| -rw-r--r-- | drivers/sbus/sbus.c | 2 | ||||
| -rw-r--r-- | drivers/serial/sunhv.c | 2 | ||||
| -rw-r--r-- | drivers/serial/sunsab.c | 2 | ||||
| -rw-r--r-- | drivers/serial/sunsu.c | 2 | ||||
| -rw-r--r-- | drivers/serial/sunzilog.c | 2 |
17 files changed, 186 insertions, 49 deletions
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 3473e25231d9..e3dd9303643d 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h | |||
| @@ -93,4 +93,8 @@ static inline unsigned long get_softint(void) | |||
| 93 | void __trigger_all_cpu_backtrace(void); | 93 | void __trigger_all_cpu_backtrace(void); |
| 94 | #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() | 94 | #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() |
| 95 | 95 | ||
| 96 | extern void *hardirq_stack[NR_CPUS]; | ||
| 97 | extern void *softirq_stack[NR_CPUS]; | ||
| 98 | #define __ARCH_HAS_DO_SOFTIRQ | ||
| 99 | |||
| 96 | #endif | 100 | #endif |
diff --git a/arch/sparc/include/asm/of_device.h b/arch/sparc/include/asm/of_device.h index e5f5aedc2293..bba777a416d3 100644 --- a/arch/sparc/include/asm/of_device.h +++ b/arch/sparc/include/asm/of_device.h | |||
| @@ -30,8 +30,7 @@ struct of_device | |||
| 30 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); | 30 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); |
| 31 | extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); | 31 | extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); |
| 32 | 32 | ||
| 33 | /* These are just here during the transition */ | 33 | /* This is just here during the transition */ |
| 34 | #include <linux/of_device.h> | ||
| 35 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
| 36 | 35 | ||
| 37 | #endif /* __KERNEL__ */ | 36 | #endif /* __KERNEL__ */ |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index ba43d85e8dde..9b6689d9d570 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
| @@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq) | |||
| 682 | ino, virt_irq); | 682 | ino, virt_irq); |
| 683 | } | 683 | } |
| 684 | 684 | ||
| 685 | void *hardirq_stack[NR_CPUS]; | ||
| 686 | void *softirq_stack[NR_CPUS]; | ||
| 687 | |||
| 688 | static __attribute__((always_inline)) void *set_hardirq_stack(void) | ||
| 689 | { | ||
| 690 | void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; | ||
| 691 | |||
| 692 | __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); | ||
| 693 | if (orig_sp < sp || | ||
| 694 | orig_sp > (sp + THREAD_SIZE)) { | ||
| 695 | sp += THREAD_SIZE - 192 - STACK_BIAS; | ||
| 696 | __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); | ||
| 697 | } | ||
| 698 | |||
| 699 | return orig_sp; | ||
| 700 | } | ||
| 701 | static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) | ||
| 702 | { | ||
| 703 | __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); | ||
| 704 | } | ||
| 705 | |||
| 685 | void handler_irq(int irq, struct pt_regs *regs) | 706 | void handler_irq(int irq, struct pt_regs *regs) |
| 686 | { | 707 | { |
| 687 | unsigned long pstate, bucket_pa; | 708 | unsigned long pstate, bucket_pa; |
| 688 | struct pt_regs *old_regs; | 709 | struct pt_regs *old_regs; |
| 710 | void *orig_sp; | ||
| 689 | 711 | ||
| 690 | clear_softint(1 << irq); | 712 | clear_softint(1 << irq); |
| 691 | 713 | ||
| @@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
| 703 | "i" (PSTATE_IE) | 725 | "i" (PSTATE_IE) |
| 704 | : "memory"); | 726 | : "memory"); |
| 705 | 727 | ||
| 728 | orig_sp = set_hardirq_stack(); | ||
| 729 | |||
| 706 | while (bucket_pa) { | 730 | while (bucket_pa) { |
| 707 | struct irq_desc *desc; | 731 | struct irq_desc *desc; |
| 708 | unsigned long next_pa; | 732 | unsigned long next_pa; |
| @@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
| 719 | bucket_pa = next_pa; | 743 | bucket_pa = next_pa; |
| 720 | } | 744 | } |
| 721 | 745 | ||
| 746 | restore_hardirq_stack(orig_sp); | ||
| 747 | |||
| 722 | irq_exit(); | 748 | irq_exit(); |
| 723 | set_irq_regs(old_regs); | 749 | set_irq_regs(old_regs); |
| 724 | } | 750 | } |
| 725 | 751 | ||
| 752 | void do_softirq(void) | ||
| 753 | { | ||
| 754 | unsigned long flags; | ||
| 755 | |||
| 756 | if (in_interrupt()) | ||
| 757 | return; | ||
| 758 | |||
| 759 | local_irq_save(flags); | ||
| 760 | |||
| 761 | if (local_softirq_pending()) { | ||
| 762 | void *orig_sp, *sp = softirq_stack[smp_processor_id()]; | ||
| 763 | |||
| 764 | sp += THREAD_SIZE - 192 - STACK_BIAS; | ||
| 765 | |||
| 766 | __asm__ __volatile__("mov %%sp, %0\n\t" | ||
| 767 | "mov %1, %%sp" | ||
| 768 | : "=&r" (orig_sp) | ||
| 769 | : "r" (sp)); | ||
| 770 | __do_softirq(); | ||
| 771 | __asm__ __volatile__("mov %0, %%sp" | ||
| 772 | : : "r" (orig_sp)); | ||
| 773 | } | ||
| 774 | |||
| 775 | local_irq_restore(flags); | ||
| 776 | } | ||
| 777 | |||
| 726 | #ifdef CONFIG_HOTPLUG_CPU | 778 | #ifdef CONFIG_HOTPLUG_CPU |
| 727 | void fixup_irqs(void) | 779 | void fixup_irqs(void) |
| 728 | { | 780 | { |
diff --git a/arch/sparc64/kernel/kstack.h b/arch/sparc64/kernel/kstack.h new file mode 100644 index 000000000000..4248d969272f --- /dev/null +++ b/arch/sparc64/kernel/kstack.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #ifndef _KSTACK_H | ||
| 2 | #define _KSTACK_H | ||
| 3 | |||
| 4 | #include <linux/thread_info.h> | ||
| 5 | #include <linux/sched.h> | ||
| 6 | #include <asm/ptrace.h> | ||
| 7 | #include <asm/irq.h> | ||
| 8 | |||
| 9 | /* SP must be STACK_BIAS adjusted already. */ | ||
| 10 | static inline bool kstack_valid(struct thread_info *tp, unsigned long sp) | ||
| 11 | { | ||
| 12 | unsigned long base = (unsigned long) tp; | ||
| 13 | |||
| 14 | if (sp >= (base + sizeof(struct thread_info)) && | ||
| 15 | sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) | ||
| 16 | return true; | ||
| 17 | |||
| 18 | if (hardirq_stack[tp->cpu]) { | ||
| 19 | base = (unsigned long) hardirq_stack[tp->cpu]; | ||
| 20 | if (sp >= base && | ||
| 21 | sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) | ||
| 22 | return true; | ||
| 23 | base = (unsigned long) softirq_stack[tp->cpu]; | ||
| 24 | if (sp >= base && | ||
| 25 | sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) | ||
| 26 | return true; | ||
| 27 | } | ||
| 28 | return false; | ||
| 29 | } | ||
| 30 | |||
| 31 | /* Does "regs" point to a valid pt_regs trap frame? */ | ||
| 32 | static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs) | ||
| 33 | { | ||
| 34 | unsigned long base = (unsigned long) tp; | ||
| 35 | unsigned long addr = (unsigned long) regs; | ||
| 36 | |||
| 37 | if (addr >= base && | ||
| 38 | addr <= (base + THREAD_SIZE - sizeof(*regs))) | ||
| 39 | goto check_magic; | ||
| 40 | |||
| 41 | if (hardirq_stack[tp->cpu]) { | ||
| 42 | base = (unsigned long) hardirq_stack[tp->cpu]; | ||
| 43 | if (addr >= base && | ||
| 44 | addr <= (base + THREAD_SIZE - sizeof(*regs))) | ||
| 45 | goto check_magic; | ||
| 46 | base = (unsigned long) softirq_stack[tp->cpu]; | ||
| 47 | if (addr >= base && | ||
| 48 | addr <= (base + THREAD_SIZE - sizeof(*regs))) | ||
| 49 | goto check_magic; | ||
| 50 | } | ||
| 51 | return false; | ||
| 52 | |||
| 53 | check_magic: | ||
| 54 | if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) | ||
| 55 | return true; | ||
| 56 | return false; | ||
| 57 | |||
| 58 | } | ||
| 59 | |||
| 60 | #endif /* _KSTACK_H */ | ||
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 7f5debdc5fed..15f4178592e7 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
| @@ -52,6 +52,8 @@ | |||
| 52 | #include <asm/irq_regs.h> | 52 | #include <asm/irq_regs.h> |
| 53 | #include <asm/smp.h> | 53 | #include <asm/smp.h> |
| 54 | 54 | ||
| 55 | #include "kstack.h" | ||
| 56 | |||
| 55 | static void sparc64_yield(int cpu) | 57 | static void sparc64_yield(int cpu) |
| 56 | { | 58 | { |
| 57 | if (tlb_type != hypervisor) | 59 | if (tlb_type != hypervisor) |
| @@ -235,19 +237,6 @@ void show_regs(struct pt_regs *regs) | |||
| 235 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; | 237 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; |
| 236 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); | 238 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); |
| 237 | 239 | ||
| 238 | static bool kstack_valid(struct thread_info *tp, struct reg_window *rw) | ||
| 239 | { | ||
| 240 | unsigned long thread_base, fp; | ||
| 241 | |||
| 242 | thread_base = (unsigned long) tp; | ||
| 243 | fp = (unsigned long) rw; | ||
| 244 | |||
| 245 | if (fp < (thread_base + sizeof(struct thread_info)) || | ||
| 246 | fp >= (thread_base + THREAD_SIZE)) | ||
| 247 | return false; | ||
| 248 | return true; | ||
| 249 | } | ||
| 250 | |||
| 251 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | 240 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, |
| 252 | int this_cpu) | 241 | int this_cpu) |
| 253 | { | 242 | { |
| @@ -264,11 +253,11 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | |||
| 264 | 253 | ||
| 265 | rw = (struct reg_window *) | 254 | rw = (struct reg_window *) |
| 266 | (regs->u_regs[UREG_FP] + STACK_BIAS); | 255 | (regs->u_regs[UREG_FP] + STACK_BIAS); |
| 267 | if (kstack_valid(tp, rw)) { | 256 | if (kstack_valid(tp, (unsigned long) rw)) { |
| 268 | global_reg_snapshot[this_cpu].i7 = rw->ins[7]; | 257 | global_reg_snapshot[this_cpu].i7 = rw->ins[7]; |
| 269 | rw = (struct reg_window *) | 258 | rw = (struct reg_window *) |
| 270 | (rw->ins[6] + STACK_BIAS); | 259 | (rw->ins[6] + STACK_BIAS); |
| 271 | if (kstack_valid(tp, rw)) | 260 | if (kstack_valid(tp, (unsigned long) rw)) |
| 272 | global_reg_snapshot[this_cpu].rpc = rw->ins[7]; | 261 | global_reg_snapshot[this_cpu].rpc = rw->ins[7]; |
| 273 | } | 262 | } |
| 274 | } else { | 263 | } else { |
| @@ -828,7 +817,7 @@ out: | |||
| 828 | unsigned long get_wchan(struct task_struct *task) | 817 | unsigned long get_wchan(struct task_struct *task) |
| 829 | { | 818 | { |
| 830 | unsigned long pc, fp, bias = 0; | 819 | unsigned long pc, fp, bias = 0; |
| 831 | unsigned long thread_info_base; | 820 | struct thread_info *tp; |
| 832 | struct reg_window *rw; | 821 | struct reg_window *rw; |
| 833 | unsigned long ret = 0; | 822 | unsigned long ret = 0; |
| 834 | int count = 0; | 823 | int count = 0; |
| @@ -837,14 +826,12 @@ unsigned long get_wchan(struct task_struct *task) | |||
| 837 | task->state == TASK_RUNNING) | 826 | task->state == TASK_RUNNING) |
| 838 | goto out; | 827 | goto out; |
| 839 | 828 | ||
| 840 | thread_info_base = (unsigned long) task_stack_page(task); | 829 | tp = task_thread_info(task); |
| 841 | bias = STACK_BIAS; | 830 | bias = STACK_BIAS; |
| 842 | fp = task_thread_info(task)->ksp + bias; | 831 | fp = task_thread_info(task)->ksp + bias; |
| 843 | 832 | ||
| 844 | do { | 833 | do { |
| 845 | /* Bogus frame pointer? */ | 834 | if (!kstack_valid(tp, fp)) |
| 846 | if (fp < (thread_info_base + sizeof(struct thread_info)) || | ||
| 847 | fp >= (thread_info_base + THREAD_SIZE)) | ||
| 848 | break; | 835 | break; |
| 849 | rw = (struct reg_window *) fp; | 836 | rw = (struct reg_window *) fp; |
| 850 | pc = rw->ins[7]; | 837 | pc = rw->ins[7]; |
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 27b81775a4de..743ccad61c60 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
| @@ -858,9 +858,7 @@ void smp_tsb_sync(struct mm_struct *mm) | |||
| 858 | extern unsigned long xcall_flush_tlb_mm; | 858 | extern unsigned long xcall_flush_tlb_mm; |
| 859 | extern unsigned long xcall_flush_tlb_pending; | 859 | extern unsigned long xcall_flush_tlb_pending; |
| 860 | extern unsigned long xcall_flush_tlb_kernel_range; | 860 | extern unsigned long xcall_flush_tlb_kernel_range; |
| 861 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 862 | extern unsigned long xcall_fetch_glob_regs; | 861 | extern unsigned long xcall_fetch_glob_regs; |
| 863 | #endif | ||
| 864 | extern unsigned long xcall_receive_signal; | 862 | extern unsigned long xcall_receive_signal; |
| 865 | extern unsigned long xcall_new_mmu_context_version; | 863 | extern unsigned long xcall_new_mmu_context_version; |
| 866 | #ifdef CONFIG_KGDB | 864 | #ifdef CONFIG_KGDB |
| @@ -1005,12 +1003,10 @@ void kgdb_roundup_cpus(unsigned long flags) | |||
| 1005 | } | 1003 | } |
| 1006 | #endif | 1004 | #endif |
| 1007 | 1005 | ||
| 1008 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 1009 | void smp_fetch_global_regs(void) | 1006 | void smp_fetch_global_regs(void) |
| 1010 | { | 1007 | { |
| 1011 | smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0); | 1008 | smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0); |
| 1012 | } | 1009 | } |
| 1013 | #endif | ||
| 1014 | 1010 | ||
| 1015 | /* We know that the window frames of the user have been flushed | 1011 | /* We know that the window frames of the user have been flushed |
| 1016 | * to the stack before we get here because all callers of us | 1012 | * to the stack before we get here because all callers of us |
diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index e9d7f0660f2e..4e21d4a57d3b 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c | |||
| @@ -5,10 +5,12 @@ | |||
| 5 | #include <asm/ptrace.h> | 5 | #include <asm/ptrace.h> |
| 6 | #include <asm/stacktrace.h> | 6 | #include <asm/stacktrace.h> |
| 7 | 7 | ||
| 8 | #include "kstack.h" | ||
| 9 | |||
| 8 | void save_stack_trace(struct stack_trace *trace) | 10 | void save_stack_trace(struct stack_trace *trace) |
| 9 | { | 11 | { |
| 10 | unsigned long ksp, fp, thread_base; | ||
| 11 | struct thread_info *tp = task_thread_info(current); | 12 | struct thread_info *tp = task_thread_info(current); |
| 13 | unsigned long ksp, fp; | ||
| 12 | 14 | ||
| 13 | stack_trace_flush(); | 15 | stack_trace_flush(); |
| 14 | 16 | ||
| @@ -18,23 +20,18 @@ void save_stack_trace(struct stack_trace *trace) | |||
| 18 | ); | 20 | ); |
| 19 | 21 | ||
| 20 | fp = ksp + STACK_BIAS; | 22 | fp = ksp + STACK_BIAS; |
| 21 | thread_base = (unsigned long) tp; | ||
| 22 | do { | 23 | do { |
| 23 | struct sparc_stackf *sf; | 24 | struct sparc_stackf *sf; |
| 24 | struct pt_regs *regs; | 25 | struct pt_regs *regs; |
| 25 | unsigned long pc; | 26 | unsigned long pc; |
| 26 | 27 | ||
| 27 | /* Bogus frame pointer? */ | 28 | if (!kstack_valid(tp, fp)) |
| 28 | if (fp < (thread_base + sizeof(struct thread_info)) || | ||
| 29 | fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf))) | ||
| 30 | break; | 29 | break; |
| 31 | 30 | ||
| 32 | sf = (struct sparc_stackf *) fp; | 31 | sf = (struct sparc_stackf *) fp; |
| 33 | regs = (struct pt_regs *) (sf + 1); | 32 | regs = (struct pt_regs *) (sf + 1); |
| 34 | 33 | ||
| 35 | if (((unsigned long)regs <= | 34 | if (kstack_is_trap_frame(tp, regs)) { |
| 36 | (thread_base + THREAD_SIZE - sizeof(*regs))) && | ||
| 37 | (regs->magic & ~0x1ff) == PT_REGS_MAGIC) { | ||
| 38 | if (!(regs->tstate & TSTATE_PRIV)) | 35 | if (!(regs->tstate & TSTATE_PRIV)) |
| 39 | break; | 36 | break; |
| 40 | pc = regs->tpc; | 37 | pc = regs->tpc; |
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 404e8561e2d0..3d924121c796 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 40 | 40 | ||
| 41 | #include "entry.h" | 41 | #include "entry.h" |
| 42 | #include "kstack.h" | ||
| 42 | 43 | ||
| 43 | /* When an irrecoverable trap occurs at tl > 0, the trap entry | 44 | /* When an irrecoverable trap occurs at tl > 0, the trap entry |
| 44 | * code logs the trap state registers at every level in the trap | 45 | * code logs the trap state registers at every level in the trap |
| @@ -2115,14 +2116,12 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
| 2115 | struct pt_regs *regs; | 2116 | struct pt_regs *regs; |
| 2116 | unsigned long pc; | 2117 | unsigned long pc; |
| 2117 | 2118 | ||
| 2118 | /* Bogus frame pointer? */ | 2119 | if (!kstack_valid(tp, fp)) |
| 2119 | if (fp < (thread_base + sizeof(struct thread_info)) || | ||
| 2120 | fp >= (thread_base + THREAD_SIZE)) | ||
| 2121 | break; | 2120 | break; |
| 2122 | sf = (struct sparc_stackf *) fp; | 2121 | sf = (struct sparc_stackf *) fp; |
| 2123 | regs = (struct pt_regs *) (sf + 1); | 2122 | regs = (struct pt_regs *) (sf + 1); |
| 2124 | 2123 | ||
| 2125 | if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) { | 2124 | if (kstack_is_trap_frame(tp, regs)) { |
| 2126 | if (!(regs->tstate & TSTATE_PRIV)) | 2125 | if (!(regs->tstate & TSTATE_PRIV)) |
| 2127 | break; | 2126 | break; |
| 2128 | pc = regs->tpc; | 2127 | pc = regs->tpc; |
diff --git a/arch/sparc64/lib/mcount.S b/arch/sparc64/lib/mcount.S index 7735a7a60533..fad90ddb3a28 100644 --- a/arch/sparc64/lib/mcount.S +++ b/arch/sparc64/lib/mcount.S | |||
| @@ -48,12 +48,45 @@ mcount: | |||
| 48 | sub %g3, STACK_BIAS, %g3 | 48 | sub %g3, STACK_BIAS, %g3 |
| 49 | cmp %sp, %g3 | 49 | cmp %sp, %g3 |
| 50 | bg,pt %xcc, 1f | 50 | bg,pt %xcc, 1f |
| 51 | sethi %hi(panicstring), %g3 | 51 | nop |
| 52 | lduh [%g6 + TI_CPU], %g1 | ||
| 53 | sethi %hi(hardirq_stack), %g3 | ||
| 54 | or %g3, %lo(hardirq_stack), %g3 | ||
| 55 | sllx %g1, 3, %g1 | ||
| 56 | ldx [%g3 + %g1], %g7 | ||
| 57 | sub %g7, STACK_BIAS, %g7 | ||
| 58 | cmp %sp, %g7 | ||
| 59 | bleu,pt %xcc, 2f | ||
| 60 | sethi %hi(THREAD_SIZE), %g3 | ||
| 61 | add %g7, %g3, %g7 | ||
| 62 | cmp %sp, %g7 | ||
| 63 | blu,pn %xcc, 1f | ||
| 64 | 2: sethi %hi(softirq_stack), %g3 | ||
| 65 | or %g3, %lo(softirq_stack), %g3 | ||
| 66 | ldx [%g3 + %g1], %g7 | ||
| 67 | cmp %sp, %g7 | ||
| 68 | bleu,pt %xcc, 2f | ||
| 69 | sethi %hi(THREAD_SIZE), %g3 | ||
| 70 | add %g7, %g3, %g7 | ||
| 71 | cmp %sp, %g7 | ||
| 72 | blu,pn %xcc, 1f | ||
| 73 | nop | ||
| 74 | /* If we are already on ovstack, don't hop onto it | ||
| 75 | * again, we are already trying to output the stack overflow | ||
| 76 | * message. | ||
| 77 | */ | ||
| 52 | sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough | 78 | sethi %hi(ovstack), %g7 ! cant move to panic stack fast enough |
| 53 | or %g7, %lo(ovstack), %g7 | 79 | or %g7, %lo(ovstack), %g7 |
| 54 | add %g7, OVSTACKSIZE, %g7 | 80 | add %g7, OVSTACKSIZE, %g3 |
| 81 | sub %g3, STACK_BIAS + 192, %g3 | ||
| 55 | sub %g7, STACK_BIAS, %g7 | 82 | sub %g7, STACK_BIAS, %g7 |
| 56 | mov %g7, %sp | 83 | cmp %sp, %g7 |
| 84 | blu,pn %xcc, 2f | ||
| 85 | cmp %sp, %g3 | ||
| 86 | bleu,pn %xcc, 1f | ||
| 87 | nop | ||
| 88 | 2: mov %g3, %sp | ||
| 89 | sethi %hi(panicstring), %g3 | ||
| 57 | call prom_printf | 90 | call prom_printf |
| 58 | or %g3, %lo(panicstring), %o0 | 91 | or %g3, %lo(panicstring), %o0 |
| 59 | call prom_halt | 92 | call prom_halt |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 4e821b3ecb03..217de3ea29e8 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <asm/sstate.h> | 49 | #include <asm/sstate.h> |
| 50 | #include <asm/mdesc.h> | 50 | #include <asm/mdesc.h> |
| 51 | #include <asm/cpudata.h> | 51 | #include <asm/cpudata.h> |
| 52 | #include <asm/irq.h> | ||
| 52 | 53 | ||
| 53 | #define MAX_PHYS_ADDRESS (1UL << 42UL) | 54 | #define MAX_PHYS_ADDRESS (1UL << 42UL) |
| 54 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) | 55 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) |
| @@ -1771,6 +1772,16 @@ void __init paging_init(void) | |||
| 1771 | if (tlb_type == hypervisor) | 1772 | if (tlb_type == hypervisor) |
| 1772 | sun4v_mdesc_init(); | 1773 | sun4v_mdesc_init(); |
| 1773 | 1774 | ||
| 1775 | /* Once the OF device tree and MDESC have been setup, we know | ||
| 1776 | * the list of possible cpus. Therefore we can allocate the | ||
| 1777 | * IRQ stacks. | ||
| 1778 | */ | ||
| 1779 | for_each_possible_cpu(i) { | ||
| 1780 | /* XXX Use node local allocations... XXX */ | ||
| 1781 | softirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
| 1782 | hardirq_stack[i] = __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
| 1783 | } | ||
| 1784 | |||
| 1774 | /* Setup bootmem... */ | 1785 | /* Setup bootmem... */ |
| 1775 | last_valid_pfn = end_pfn = bootmem_init(phys_base); | 1786 | last_valid_pfn = end_pfn = bootmem_init(phys_base); |
| 1776 | 1787 | ||
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index ff1dc44d363e..86773e89dc1b 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S | |||
| @@ -480,7 +480,6 @@ xcall_sync_tick: | |||
| 480 | b rtrap_xcall | 480 | b rtrap_xcall |
| 481 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 | 481 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 |
| 482 | 482 | ||
| 483 | #ifdef CONFIG_MAGIC_SYSRQ | ||
| 484 | .globl xcall_fetch_glob_regs | 483 | .globl xcall_fetch_glob_regs |
| 485 | xcall_fetch_glob_regs: | 484 | xcall_fetch_glob_regs: |
| 486 | sethi %hi(global_reg_snapshot), %g1 | 485 | sethi %hi(global_reg_snapshot), %g1 |
| @@ -511,7 +510,6 @@ xcall_fetch_glob_regs: | |||
| 511 | membar #StoreStore | 510 | membar #StoreStore |
| 512 | stx %g3, [%g1 + GR_SNAP_THREAD] | 511 | stx %g3, [%g1 + GR_SNAP_THREAD] |
| 513 | retry | 512 | retry |
| 514 | #endif /* CONFIG_MAGIC_SYSRQ */ | ||
| 515 | 513 | ||
| 516 | #ifdef DCACHE_ALIASING_POSSIBLE | 514 | #ifdef DCACHE_ALIASING_POSSIBLE |
| 517 | .align 32 | 515 | .align 32 |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index 66bafe308b0c..692a79ec2a22 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | #ifndef _I8042_SPARCIO_H | 1 | #ifndef _I8042_SPARCIO_H |
| 2 | #define _I8042_SPARCIO_H | 2 | #define _I8042_SPARCIO_H |
| 3 | 3 | ||
| 4 | #include <linux/of_device.h> | ||
| 5 | |||
| 4 | #include <asm/io.h> | 6 | #include <asm/io.h> |
| 5 | #include <asm/oplib.h> | 7 | #include <asm/oplib.h> |
| 6 | #include <asm/prom.h> | 8 | #include <asm/prom.h> |
| 7 | #include <asm/of_device.h> | ||
| 8 | 9 | ||
| 9 | static int i8042_kbd_irq = -1; | 10 | static int i8042_kbd_irq = -1; |
| 10 | static int i8042_aux_irq = -1; | 11 | static int i8042_aux_irq = -1; |
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 73a86d09bba8..9c129248466c 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c | |||
| @@ -7,13 +7,13 @@ | |||
| 7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/device.h> | 9 | #include <linux/device.h> |
| 10 | #include <linux/of_device.h> | ||
| 10 | 11 | ||
| 11 | #include <asm/system.h> | 12 | #include <asm/system.h> |
| 12 | #include <asm/sbus.h> | 13 | #include <asm/sbus.h> |
| 13 | #include <asm/dma.h> | 14 | #include <asm/dma.h> |
| 14 | #include <asm/oplib.h> | 15 | #include <asm/oplib.h> |
| 15 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
| 16 | #include <asm/of_device.h> | ||
| 17 | #include <asm/bpp.h> | 17 | #include <asm/bpp.h> |
| 18 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
| 19 | 19 | ||
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index aeeec5588afd..e41766d08035 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
| @@ -17,11 +17,11 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/of_device.h> | ||
| 20 | 21 | ||
| 21 | #include <asm/hypervisor.h> | 22 | #include <asm/hypervisor.h> |
| 22 | #include <asm/spitfire.h> | 23 | #include <asm/spitfire.h> |
| 23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
| 24 | #include <asm/of_device.h> | ||
| 25 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
| 26 | 26 | ||
| 27 | #if defined(CONFIG_MAGIC_SYSRQ) | 27 | #if defined(CONFIG_MAGIC_SYSRQ) |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 15ee497e1c78..29b4458abf74 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
| @@ -32,11 +32,11 @@ | |||
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/of_device.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 37 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
| 38 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 39 | #include <asm/of_device.h> | ||
| 40 | 40 | ||
| 41 | #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 41 | #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
| 42 | #define SUPPORT_SYSRQ | 42 | #define SUPPORT_SYSRQ |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index e24e68235088..a378464f9292 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
| @@ -35,11 +35,11 @@ | |||
| 35 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> |
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
| 38 | #include <linux/of_device.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 40 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
| 41 | #include <asm/prom.h> | 42 | #include <asm/prom.h> |
| 42 | #include <asm/of_device.h> | ||
| 43 | 43 | ||
| 44 | #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 44 | #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
| 45 | #define SUPPORT_SYSRQ | 45 | #define SUPPORT_SYSRQ |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 0f3d69b86d67..3cb4c8aee13f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
| @@ -32,11 +32,11 @@ | |||
| 32 | #include <linux/serio.h> | 32 | #include <linux/serio.h> |
| 33 | #endif | 33 | #endif |
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/of_device.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 37 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
| 38 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 39 | #include <asm/of_device.h> | ||
| 40 | 40 | ||
| 41 | #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 41 | #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
| 42 | #define SUPPORT_SYSRQ | 42 | #define SUPPORT_SYSRQ |
