Loading arch/sparc/include/asm/irq_64.h +4 −0 Original line number Diff line number Diff line Loading @@ -93,4 +93,8 @@ static inline unsigned long get_softint(void) void __trigger_all_cpu_backtrace(void); #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() extern void *hardirq_stack[NR_CPUS]; extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ #endif arch/sparc64/kernel/irq.c +52 −0 Original line number Diff line number Diff line Loading @@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq) ino, virt_irq); } void *hardirq_stack[NR_CPUS]; void *softirq_stack[NR_CPUS]; static __attribute__((always_inline)) void *set_hardirq_stack(void) { void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); if (orig_sp < sp || orig_sp > (sp + THREAD_SIZE)) { sp += THREAD_SIZE - 192 - STACK_BIAS; __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); } return orig_sp; } static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) { __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); } void handler_irq(int irq, struct pt_regs *regs) { unsigned long pstate, bucket_pa; struct pt_regs *old_regs; void *orig_sp; clear_softint(1 << irq); Loading @@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs *regs) "i" (PSTATE_IE) : "memory"); orig_sp = set_hardirq_stack(); while (bucket_pa) { struct irq_desc *desc; unsigned long next_pa; Loading @@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs *regs) bucket_pa = next_pa; } restore_hardirq_stack(orig_sp); irq_exit(); set_irq_regs(old_regs); } void do_softirq(void) { unsigned long flags; if (in_interrupt()) return; local_irq_save(flags); if (local_softirq_pending()) { void *orig_sp, *sp = softirq_stack[smp_processor_id()]; sp += THREAD_SIZE - 192 - STACK_BIAS; __asm__ __volatile__("mov %%sp, %0\n\t" "mov %1, %%sp" : "=&r" (orig_sp) : "r" (sp)); __do_softirq(); __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); } local_irq_restore(flags); } #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) { Loading arch/sparc64/kernel/kstack.h 0 → 100644 +58 −0 Original line number Diff line number Diff line #ifndef _KSTACK_H #define _KSTACK_H #include <linux/thread_info.h> #include <linux/sched.h> #include <asm/ptrace.h> #include <asm/irq.h> /* SP must be STACK_BIAS adjusted already. */ static inline bool kstack_valid(struct thread_info *tp, unsigned long sp) { unsigned long base = (unsigned long) tp; if (sp >= (base + sizeof(struct thread_info)) && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; base = (unsigned long) hardirq_stack[tp->cpu]; if (sp >= base && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; base = (unsigned long) softirq_stack[tp->cpu]; if (sp >= base && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; return false; } /* Does "regs" point to a valid pt_regs trap frame? */ static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs) { unsigned long base = (unsigned long) tp; unsigned long addr = (unsigned long) regs; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; base = (unsigned long) hardirq_stack[tp->cpu]; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; base = (unsigned long) softirq_stack[tp->cpu]; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; return false; check_magic: if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) return true; return false; } #endif /* _KSTACK_H */ arch/sparc64/kernel/process.c +7 −20 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include <asm/irq_regs.h> #include <asm/smp.h> #include "kstack.h" static void sparc64_yield(int cpu) { if (tlb_type != hypervisor) Loading Loading @@ -235,19 +237,6 @@ void show_regs(struct pt_regs *regs) struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; static DEFINE_SPINLOCK(global_reg_snapshot_lock); static bool kstack_valid(struct thread_info *tp, struct reg_window *rw) { unsigned long thread_base, fp; thread_base = (unsigned long) tp; fp = (unsigned long) rw; if (fp < (thread_base + sizeof(struct thread_info)) || fp >= (thread_base + THREAD_SIZE)) return false; return true; } static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, int this_cpu) { Loading @@ -264,11 +253,11 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); if (kstack_valid(tp, rw)) { if (kstack_valid(tp, (unsigned long) rw)) { global_reg_snapshot[this_cpu].i7 = rw->ins[7]; rw = (struct reg_window *) (rw->ins[6] + STACK_BIAS); if (kstack_valid(tp, rw)) if (kstack_valid(tp, (unsigned long) rw)) global_reg_snapshot[this_cpu].rpc = rw->ins[7]; } } else { Loading Loading @@ -828,7 +817,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs) unsigned long get_wchan(struct task_struct *task) { unsigned long pc, fp, bias = 0; unsigned long thread_info_base; struct thread_info *tp; struct reg_window *rw; unsigned long ret = 0; int count = 0; Loading @@ -837,14 +826,12 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; thread_info_base = (unsigned long) task_stack_page(task); tp = task_thread_info(task); bias = STACK_BIAS; fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ if (fp < (thread_info_base + sizeof(struct thread_info)) || fp >= (thread_info_base + THREAD_SIZE)) if (!kstack_valid(tp, fp)) break; rw = (struct reg_window *) fp; pc = rw->ins[7]; Loading arch/sparc64/kernel/stacktrace.c +4 −6 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ #include <asm/ptrace.h> #include <asm/stacktrace.h> #include "kstack.h" void save_stack_trace(struct stack_trace *trace) { unsigned long ksp, fp, thread_base; Loading @@ -24,17 +26,13 @@ void save_stack_trace(struct stack_trace *trace) struct pt_regs *regs; unsigned long pc; /* Bogus frame pointer? */ if (fp < (thread_base + sizeof(struct thread_info)) || fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf))) if (!kstack_valid(tp, fp)) break; sf = (struct sparc_stackf *) fp; regs = (struct pt_regs *) (sf + 1); if (((unsigned long)regs <= (thread_base + THREAD_SIZE - sizeof(*regs))) && (regs->magic & ~0x1ff) == PT_REGS_MAGIC) { if (kstack_is_trap_frame(tp, regs)) { if (!(regs->tstate & TSTATE_PRIV)) break; pc = regs->tpc; Loading Loading
arch/sparc/include/asm/irq_64.h +4 −0 Original line number Diff line number Diff line Loading @@ -93,4 +93,8 @@ static inline unsigned long get_softint(void) void __trigger_all_cpu_backtrace(void); #define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace() extern void *hardirq_stack[NR_CPUS]; extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ #endif
arch/sparc64/kernel/irq.c +52 −0 Original line number Diff line number Diff line Loading @@ -682,10 +682,32 @@ void ack_bad_irq(unsigned int virt_irq) ino, virt_irq); } void *hardirq_stack[NR_CPUS]; void *softirq_stack[NR_CPUS]; static __attribute__((always_inline)) void *set_hardirq_stack(void) { void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); if (orig_sp < sp || orig_sp > (sp + THREAD_SIZE)) { sp += THREAD_SIZE - 192 - STACK_BIAS; __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); } return orig_sp; } static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) { __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); } void handler_irq(int irq, struct pt_regs *regs) { unsigned long pstate, bucket_pa; struct pt_regs *old_regs; void *orig_sp; clear_softint(1 << irq); Loading @@ -703,6 +725,8 @@ void handler_irq(int irq, struct pt_regs *regs) "i" (PSTATE_IE) : "memory"); orig_sp = set_hardirq_stack(); while (bucket_pa) { struct irq_desc *desc; unsigned long next_pa; Loading @@ -719,10 +743,38 @@ void handler_irq(int irq, struct pt_regs *regs) bucket_pa = next_pa; } restore_hardirq_stack(orig_sp); irq_exit(); set_irq_regs(old_regs); } void do_softirq(void) { unsigned long flags; if (in_interrupt()) return; local_irq_save(flags); if (local_softirq_pending()) { void *orig_sp, *sp = softirq_stack[smp_processor_id()]; sp += THREAD_SIZE - 192 - STACK_BIAS; __asm__ __volatile__("mov %%sp, %0\n\t" "mov %1, %%sp" : "=&r" (orig_sp) : "r" (sp)); __do_softirq(); __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); } local_irq_restore(flags); } #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) { Loading
arch/sparc64/kernel/kstack.h 0 → 100644 +58 −0 Original line number Diff line number Diff line #ifndef _KSTACK_H #define _KSTACK_H #include <linux/thread_info.h> #include <linux/sched.h> #include <asm/ptrace.h> #include <asm/irq.h> /* SP must be STACK_BIAS adjusted already. */ static inline bool kstack_valid(struct thread_info *tp, unsigned long sp) { unsigned long base = (unsigned long) tp; if (sp >= (base + sizeof(struct thread_info)) && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; base = (unsigned long) hardirq_stack[tp->cpu]; if (sp >= base && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; base = (unsigned long) softirq_stack[tp->cpu]; if (sp >= base && sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf))) return true; return false; } /* Does "regs" point to a valid pt_regs trap frame? */ static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs) { unsigned long base = (unsigned long) tp; unsigned long addr = (unsigned long) regs; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; base = (unsigned long) hardirq_stack[tp->cpu]; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; base = (unsigned long) softirq_stack[tp->cpu]; if (addr >= base && addr <= (base + THREAD_SIZE - sizeof(*regs))) goto check_magic; return false; check_magic: if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) return true; return false; } #endif /* _KSTACK_H */
arch/sparc64/kernel/process.c +7 −20 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ #include <asm/irq_regs.h> #include <asm/smp.h> #include "kstack.h" static void sparc64_yield(int cpu) { if (tlb_type != hypervisor) Loading Loading @@ -235,19 +237,6 @@ void show_regs(struct pt_regs *regs) struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; static DEFINE_SPINLOCK(global_reg_snapshot_lock); static bool kstack_valid(struct thread_info *tp, struct reg_window *rw) { unsigned long thread_base, fp; thread_base = (unsigned long) tp; fp = (unsigned long) rw; if (fp < (thread_base + sizeof(struct thread_info)) || fp >= (thread_base + THREAD_SIZE)) return false; return true; } static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, int this_cpu) { Loading @@ -264,11 +253,11 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); if (kstack_valid(tp, rw)) { if (kstack_valid(tp, (unsigned long) rw)) { global_reg_snapshot[this_cpu].i7 = rw->ins[7]; rw = (struct reg_window *) (rw->ins[6] + STACK_BIAS); if (kstack_valid(tp, rw)) if (kstack_valid(tp, (unsigned long) rw)) global_reg_snapshot[this_cpu].rpc = rw->ins[7]; } } else { Loading Loading @@ -828,7 +817,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs) unsigned long get_wchan(struct task_struct *task) { unsigned long pc, fp, bias = 0; unsigned long thread_info_base; struct thread_info *tp; struct reg_window *rw; unsigned long ret = 0; int count = 0; Loading @@ -837,14 +826,12 @@ unsigned long get_wchan(struct task_struct *task) task->state == TASK_RUNNING) goto out; thread_info_base = (unsigned long) task_stack_page(task); tp = task_thread_info(task); bias = STACK_BIAS; fp = task_thread_info(task)->ksp + bias; do { /* Bogus frame pointer? */ if (fp < (thread_info_base + sizeof(struct thread_info)) || fp >= (thread_info_base + THREAD_SIZE)) if (!kstack_valid(tp, fp)) break; rw = (struct reg_window *) fp; pc = rw->ins[7]; Loading
arch/sparc64/kernel/stacktrace.c +4 −6 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ #include <asm/ptrace.h> #include <asm/stacktrace.h> #include "kstack.h" void save_stack_trace(struct stack_trace *trace) { unsigned long ksp, fp, thread_base; Loading @@ -24,17 +26,13 @@ void save_stack_trace(struct stack_trace *trace) struct pt_regs *regs; unsigned long pc; /* Bogus frame pointer? */ if (fp < (thread_base + sizeof(struct thread_info)) || fp > (thread_base + THREAD_SIZE - sizeof(struct sparc_stackf))) if (!kstack_valid(tp, fp)) break; sf = (struct sparc_stackf *) fp; regs = (struct pt_regs *) (sf + 1); if (((unsigned long)regs <= (thread_base + THREAD_SIZE - sizeof(*regs))) && (regs->magic & ~0x1ff) == PT_REGS_MAGIC) { if (kstack_is_trap_frame(tp, regs)) { if (!(regs->tstate & TSTATE_PRIV)) break; pc = regs->tpc; Loading