Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 198181
b: refs/heads/master
c: 2a12c46
h: refs/heads/master
i:
  198179: 991b414
v: v3
  • Loading branch information
Robin Getz authored and Mike Frysinger committed May 21, 2010
1 parent 33cc5bd commit 6c0b7ab
Show file tree
Hide file tree
Showing 8 changed files with 888 additions and 837 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bb84dbf69b0730fcc78c275f900ed74b2b8453a5
refs/heads/master: 2a12c4632db1c0c548a7023e63869b27c7789a92
2 changes: 2 additions & 0 deletions trunk/arch/blackfin/include/asm/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#ifndef __ASSEMBLY__
extern unsigned long trace_buff_offset;
extern unsigned long software_trace_buff[];
extern void decode_address(char *buf, unsigned long address);
extern bool get_instruction(unsigned short *val, unsigned short *address);

/* Trace Macros for C files */

Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/blackfin/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ extra-y := init_task.o vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o
fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o \
trace.o exception.o dumpstack.o

ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
obj-y += time-ts.o
Expand Down
181 changes: 181 additions & 0 deletions trunk/arch/blackfin/kernel/dumpstack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/* Provide basic stack dumping functions
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/

#include <linux/kernel.h>
#include <linux/thread_info.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <asm/trace.h>

/*
* Checks to see if the address pointed to is either a
* 16-bit CALL instruction, or a 32-bit CALL instruction
*/
static bool is_bfin_call(unsigned short *addr)
{
unsigned short opcode = 0, *ins_addr;
ins_addr = (unsigned short *)addr;

if (!get_instruction(&opcode, ins_addr))
return false;

if ((opcode >= 0x0060 && opcode <= 0x0067) ||
(opcode >= 0x0070 && opcode <= 0x0077))
return true;

ins_addr--;
if (!get_instruction(&opcode, ins_addr))
return false;

if (opcode >= 0xE300 && opcode <= 0xE3FF)
return true;

return false;

}

void show_stack(struct task_struct *task, unsigned long *stack)
{
#ifdef CONFIG_PRINTK
unsigned int *addr, *endstack, *fp = 0, *frame;
unsigned short *ins_addr;
char buf[150];
unsigned int i, j, ret_addr, frame_no = 0;

/*
* If we have been passed a specific stack, use that one otherwise
* if we have been passed a task structure, use that, otherwise
* use the stack of where the variable "stack" exists
*/

if (stack == NULL) {
if (task) {
/* We know this is a kernel stack, so this is the start/end */
stack = (unsigned long *)task->thread.ksp;
endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
} else {
/* print out the existing stack info */
stack = (unsigned long *)&stack;
endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
}
} else
endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);

printk(KERN_NOTICE "Stack info:\n");
decode_address(buf, (unsigned int)stack);
printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);

if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
printk(KERN_NOTICE "Invalid stack pointer\n");
return;
}

/* First thing is to look for a frame pointer */
for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
if (*addr & 0x1)
continue;
ins_addr = (unsigned short *)*addr;
ins_addr--;
if (is_bfin_call(ins_addr))
fp = addr - 1;

if (fp) {
/* Let's check to see if it is a frame pointer */
while (fp >= (addr - 1) && fp < endstack
&& fp && ((unsigned int) fp & 0x3) == 0)
fp = (unsigned int *)*fp;
if (fp == 0 || fp == endstack) {
fp = addr - 1;
break;
}
fp = 0;
}
}
if (fp) {
frame = fp;
printk(KERN_NOTICE " FP: (0x%p)\n", fp);
} else
frame = 0;

/*
* Now that we think we know where things are, we
* walk the stack again, this time printing things out
* incase there is no frame pointer, we still look for
* valid return addresses
*/

/* First time print out data, next time, print out symbols */
for (j = 0; j <= 1; j++) {
if (j)
printk(KERN_NOTICE "Return addresses in stack:\n");
else
printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);

fp = frame;
frame_no = 0;

for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
addr < endstack; addr++, i++) {

ret_addr = 0;
if (!j && i % 8 == 0)
printk(KERN_NOTICE "%p:", addr);

/* if it is an odd address, or zero, just skip it */
if (*addr & 0x1 || !*addr)
goto print;

ins_addr = (unsigned short *)*addr;

/* Go back one instruction, and see if it is a CALL */
ins_addr--;
ret_addr = is_bfin_call(ins_addr);
print:
if (!j && stack == (unsigned long *)addr)
printk("[%08x]", *addr);
else if (ret_addr)
if (j) {
decode_address(buf, (unsigned int)*addr);
if (frame == addr) {
printk(KERN_NOTICE " frame %2i : %s\n", frame_no, buf);
continue;
}
printk(KERN_NOTICE " address : %s\n", buf);
} else
printk("<%08x>", *addr);
else if (fp == addr) {
if (j)
frame = addr+1;
else
printk("(%08x)", *addr);

fp = (unsigned int *)*addr;
frame_no++;

} else if (!j)
printk(" %08x ", *addr);
}
if (!j)
printk("\n");
}
#endif
}
EXPORT_SYMBOL(show_stack);

void dump_stack(void)
{
unsigned long stack;
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int tflags;
#endif
trace_buffer_save(tflags);
dump_bfin_trace_buffer();
show_stack(current, &stack);
trace_buffer_restore(tflags);
}
EXPORT_SYMBOL(dump_stack);
45 changes: 45 additions & 0 deletions trunk/arch/blackfin/kernel/exception.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* Basic functions for adding/removing custom exception handlers
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Licensed under the GPL-2 or later
*/

#include <linux/module.h>
#include <asm/irq_handler.h>

int bfin_request_exception(unsigned int exception, void (*handler)(void))
{
void (*curr_handler)(void);

if (exception > 0x3F)
return -EINVAL;

curr_handler = ex_table[exception];

if (curr_handler != ex_replaceable)
return -EBUSY;

ex_table[exception] = handler;

return 0;
}
EXPORT_SYMBOL(bfin_request_exception);

int bfin_free_exception(unsigned int exception, void (*handler)(void))
{
void (*curr_handler)(void);

if (exception > 0x3F)
return -EINVAL;

curr_handler = ex_table[exception];

if (curr_handler != handler)
return -EBUSY;

ex_table[exception] = ex_replaceable;

return 0;
}
EXPORT_SYMBOL(bfin_free_exception);
23 changes: 23 additions & 0 deletions trunk/arch/blackfin/kernel/sys_bfin.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,26 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr,
}
EXPORT_SYMBOL(get_fb_unmapped_area);
#endif

/* Needed for legacy userspace atomic emulation */
static DEFINE_SPINLOCK(bfin_spinlock_lock);

#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
__attribute__((l1_text))
#endif
asmlinkage int sys_bfin_spinlock(int *p)
{
int ret, tmp = 0;

spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
ret = get_user(tmp, p);
if (likely(ret == 0)) {
if (unlikely(tmp))
ret = 1;
else
put_user(1, p);
}
spin_unlock(&bfin_spinlock_lock);

return ret;
}
Loading

0 comments on commit 6c0b7ab

Please sign in to comment.