Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc64: Add some more commentary to __raw_local_irq_save()
  sparc64: Fix memory leak in pci_register_iommu_region().
  sparc64: Add kmemleak annotation to sun4v_build_virq()
  sparc64: Support kmemleak.
  sparc64: Add function graph tracer support.
  sparc64: Give a stack frame to the ftrace call sites.
  sparc64: Use a seperate counter for timer interrupts and NMI checks, like x86.
  sparc64: Remove profiling from some low-level bits.
  sparc64: Kill unnecessary static on local var in ftrace_call_replace().
  sparc64: Kill CONFIG_STACK_DEBUG code.
  sparc64: Add HAVE_FUNCTION_TRACE_MCOUNT_TEST and tidy up.
  sparc64: Adjust __raw_local_irq_save() to cooperate in NMIs.
  sparc64: Use kstack_valid() in die_if_kernel().
  • Loading branch information
Linus Torvalds committed Apr 13, 2010
2 parents 465de2b + c011f80 commit 44d2d37
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 135 deletions.
3 changes: 3 additions & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ config SPARC64
def_bool 64BIT
select ARCH_SUPPORTS_MSI
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_GRAPH_FP_TEST
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES
select HAVE_KPROBES
select HAVE_LMB
Expand Down
5 changes: 1 addition & 4 deletions arch/sparc/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ config DEBUG_DCFLUSH
bool "D-cache flush debugging"
depends on SPARC64 && DEBUG_KERNEL

config STACK_DEBUG
bool "Stack Overflow Detection Support"

config MCOUNT
bool
depends on SPARC64
depends on STACK_DEBUG || FUNCTION_TRACER
depends on FUNCTION_TRACER
default y

config FRAME_POINTER
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/include/asm/cpudata_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ typedef struct {
unsigned int __nmi_count;
unsigned long clock_tick; /* %tick's per second */
unsigned long __pad;
unsigned int __pad1;
unsigned int irq0_irqs;
unsigned int __pad2;

/* Dcache line 2, rarely used */
Expand Down
23 changes: 20 additions & 3 deletions arch/sparc/include/asm/irqflags_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,26 @@ static inline int raw_irqs_disabled(void)
*/
static inline unsigned long __raw_local_irq_save(void)
{
unsigned long flags = __raw_local_save_flags();

raw_local_irq_disable();
unsigned long flags, tmp;

/* Disable interrupts to PIL_NORMAL_MAX unless we already
* are using PIL_NMI, in which case PIL_NMI is retained.
*
* The only values we ever program into the %pil are 0,
* PIL_NORMAL_MAX and PIL_NMI.
*
* Since PIL_NMI is the largest %pil value and all bits are
* set in it (0xf), it doesn't matter what PIL_NORMAL_MAX
* actually is.
*/
__asm__ __volatile__(
"rdpr %%pil, %0\n\t"
"or %0, %2, %1\n\t"
"wrpr %1, 0x0, %%pil"
: "=r" (flags), "=r" (tmp)
: "i" (PIL_NORMAL_MAX)
: "memory"
);

return flags;
}
Expand Down
10 changes: 9 additions & 1 deletion arch/sparc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ extra-y += init_task.o
CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS)
extra-y += vmlinux.lds

ifdef CONFIG_FUNCTION_TRACER
# Do not profile debug and lowlevel utilities
CFLAGS_REMOVE_ftrace.o := -pg
CFLAGS_REMOVE_time_$(BITS).o := -pg
CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg
endif

obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32) += etrap_32.o
obj-$(CONFIG_SPARC32) += rtrap_32.o
Expand Down Expand Up @@ -85,7 +93,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).o


obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
CFLAGS_REMOVE_ftrace.o := -pg
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o

obj-$(CONFIG_EARLYFB) += btext.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
Expand Down
60 changes: 59 additions & 1 deletion arch/sparc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static const u32 ftrace_nop = 0x01000000;

static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)
{
static u32 call;
u32 call;
s32 off;

off = ((s32)addr - (s32)ip);
Expand Down Expand Up @@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)
return 0;
}
#endif

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);

int ftrace_enable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
u32 old, new;

old = *(u32 *) &ftrace_graph_call;
new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller);
return ftrace_modify_code(ip, old, new);
}

int ftrace_disable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
u32 old, new;

old = *(u32 *) &ftrace_graph_call;
new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub);

return ftrace_modify_code(ip, old, new);
}

#endif /* !CONFIG_DYNAMIC_FTRACE */

/*
* Hook the return address and push it in the stack of return addrs
* in current thread info.
*/
unsigned long prepare_ftrace_return(unsigned long parent,
unsigned long self_addr,
unsigned long frame_pointer)
{
unsigned long return_hooker = (unsigned long) &return_to_handler;
struct ftrace_graph_ent trace;

if (unlikely(atomic_read(&current->tracing_graph_pause)))
return parent + 8UL;

if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
frame_pointer) == -EBUSY)
return parent + 8UL;

trace.func = self_addr;

/* Only trace if the calling function expects to */
if (!ftrace_graph_entry(&trace)) {
current->curr_ret_stack--;
return parent + 8UL;
}

return return_hooker;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
11 changes: 10 additions & 1 deletion arch/sparc/kernel/irq_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/ftrace.h>
#include <linux/irq.h>

#include <asm/ptrace.h>
Expand Down Expand Up @@ -647,6 +648,14 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
if (unlikely(!bucket))
return 0;

/* The only reference we store to the IRQ bucket is
* by physical address which kmemleak can't see, tell
* it that this object explicitly is not a leak and
* should be scanned.
*/
kmemleak_not_leak(bucket);

__flush_dcache_range((unsigned long) bucket,
((unsigned long) bucket +
sizeof(struct ino_bucket)));
Expand Down Expand Up @@ -721,7 +730,7 @@ 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)
void __irq_entry handler_irq(int irq, struct pt_regs *regs)
{
unsigned long pstate, bucket_pa;
struct pt_regs *old_regs;
Expand Down
3 changes: 2 additions & 1 deletion arch/sparc/kernel/kgdb_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <linux/kgdb.h>
#include <linux/kdebug.h>
#include <linux/ftrace.h>

#include <asm/kdebug.h>
#include <asm/ptrace.h>
Expand Down Expand Up @@ -108,7 +109,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
}

#ifdef CONFIG_SMP
void smp_kgdb_capture_client(int irq, struct pt_regs *regs)
void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
{
unsigned long flags;

Expand Down
3 changes: 1 addition & 2 deletions arch/sparc/kernel/nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
{
unsigned int sum, touched = 0;
int cpu = smp_processor_id();

clear_softint(1 << irq);

Expand All @@ -106,7 +105,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
else
pcr_ops->write(PCR_PIC_PRIV);

sum = kstat_irqs_cpu(0, cpu);
sum = local_cpu_data().irq0_irqs;
if (__get_cpu_var(nmi_touch)) {
__get_cpu_var(nmi_touch) = 0;
touched = 1;
Expand Down
11 changes: 8 additions & 3 deletions arch/sparc/kernel/pci_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,19 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm)
struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL);

if (!rp) {
prom_printf("Cannot allocate IOMMU resource.\n");
prom_halt();
pr_info("%s: Cannot allocate IOMMU resource.\n",
pbm->name);
return;
}
rp->name = "IOMMU";
rp->start = pbm->mem_space.start + (unsigned long) vdma[0];
rp->end = rp->start + (unsigned long) vdma[1] - 1UL;
rp->flags = IORESOURCE_BUSY;
request_resource(&pbm->mem_space, rp);
if (request_resource(&pbm->mem_space, rp)) {
pr_info("%s: Unable to request IOMMU resource.\n",
pbm->name);
kfree(rp);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion arch/sparc/kernel/pcr.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/irq.h>

#include <linux/perf_event.h>
#include <linux/ftrace.h>

#include <asm/pil.h>
#include <asm/pcr.h>
Expand All @@ -34,7 +35,7 @@ unsigned int picl_shift;
* Therefore in such situations we defer the work by signalling
* a lower level cpu IRQ.
*/
void deferred_pcr_work_irq(int irq, struct pt_regs *regs)
void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs;

Expand Down
11 changes: 6 additions & 5 deletions arch/sparc/kernel/smp_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/profile.h>
#include <linux/bootmem.h>
#include <linux/vmalloc.h>
#include <linux/ftrace.h>
#include <linux/cpu.h>
#include <linux/slab.h>

Expand Down Expand Up @@ -823,13 +824,13 @@ void arch_send_call_function_single_ipi(int cpu)
&cpumask_of_cpu(cpu));
}

void smp_call_function_client(int irq, struct pt_regs *regs)
void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);
generic_smp_call_function_interrupt();
}

void smp_call_function_single_client(int irq, struct pt_regs *regs)
void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);
generic_smp_call_function_single_interrupt();
Expand Down Expand Up @@ -965,7 +966,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
put_cpu();
}

void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
{
struct mm_struct *mm;
unsigned long flags;
Expand Down Expand Up @@ -1149,7 +1150,7 @@ void smp_release(void)
*/
extern void prom_world(int);

void smp_penguin_jailcell(int irq, struct pt_regs *regs)
void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);

Expand Down Expand Up @@ -1365,7 +1366,7 @@ void smp_send_reschedule(int cpu)
&cpumask_of_cpu(cpu));
}

void smp_receive_signal_client(int irq, struct pt_regs *regs)
void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);
}
Expand Down
4 changes: 3 additions & 1 deletion arch/sparc/kernel/time_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/clocksource.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/ftrace.h>

#include <asm/oplib.h>
#include <asm/timer.h>
Expand Down Expand Up @@ -717,7 +718,7 @@ static struct clock_event_device sparc64_clockevent = {
};
static DEFINE_PER_CPU(struct clock_event_device, sparc64_events);

void timer_interrupt(int irq, struct pt_regs *regs)
void __irq_entry timer_interrupt(int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
unsigned long tick_mask = tick_ops->softint_mask;
Expand All @@ -728,6 +729,7 @@ void timer_interrupt(int irq, struct pt_regs *regs)

irq_enter();

local_cpu_data().irq0_irqs++;
kstat_incr_irqs_this_cpu(0, irq_to_desc(0));

if (unlikely(!evt->event_handler)) {
Expand Down
26 changes: 3 additions & 23 deletions arch/sparc/kernel/traps_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2203,27 +2203,6 @@ void dump_stack(void)

EXPORT_SYMBOL(dump_stack);

static inline int is_kernel_stack(struct task_struct *task,
struct reg_window *rw)
{
unsigned long rw_addr = (unsigned long) rw;
unsigned long thread_base, thread_end;

if (rw_addr < PAGE_OFFSET) {
if (task != &init_task)
return 0;
}

thread_base = (unsigned long) task_stack_page(task);
thread_end = thread_base + sizeof(union thread_union);
if (rw_addr >= thread_base &&
rw_addr < thread_end &&
!(rw_addr & 0x7UL))
return 1;

return 0;
}

static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
{
unsigned long fp = rw->ins[6];
Expand Down Expand Up @@ -2252,15 +2231,16 @@ void die_if_kernel(char *str, struct pt_regs *regs)
show_regs(regs);
add_taint(TAINT_DIE);
if (regs->tstate & TSTATE_PRIV) {
struct thread_info *tp = current_thread_info();
struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);

/* Stop the back trace when we hit userland or we
* find some badly aligned kernel stack.
*/
while (rw &&
count++ < 30&&
is_kernel_stack(current, rw)) {
count++ < 30 &&
kstack_valid(tp, (unsigned long) rw)) {
printk("Caller[%016lx]: %pS\n", rw->ins[7],
(void *) rw->ins[7]);

Expand Down
Loading

0 comments on commit 44d2d37

Please sign in to comment.