Commit 442ee5a9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm

* 'fixes' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm:
  ARM: 7204/1: arch/arm/kernel/setup.c: initialize arm_dma_zone_size earlier
  ARM: 7185/1: perf: don't assign platform_device on unsupported CPUs
  ARM: 7187/1: fix unwinding for XIP kernels
  ARM: 7186/1: fix Kconfig issue with PHYS_OFFSET and !MMU
parents 13c07b02 9811ccdf
...@@ -220,8 +220,9 @@ config NEED_MACH_MEMORY_H ...@@ -220,8 +220,9 @@ config NEED_MACH_MEMORY_H
be avoided when possible. be avoided when possible.
config PHYS_OFFSET config PHYS_OFFSET
hex "Physical address of main memory" hex "Physical address of main memory" if MMU
depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
default DRAM_BASE if !MMU
help help
Please provide the physical address corresponding to the Please provide the physical address corresponding to the
location of main memory in your system. location of main memory in your system.
......
...@@ -30,14 +30,15 @@ enum unwind_reason_code { ...@@ -30,14 +30,15 @@ enum unwind_reason_code {
}; };
struct unwind_idx { struct unwind_idx {
unsigned long addr; unsigned long addr_offset;
unsigned long insn; unsigned long insn;
}; };
struct unwind_table { struct unwind_table {
struct list_head list; struct list_head list;
struct unwind_idx *start; const struct unwind_idx *start;
struct unwind_idx *stop; const struct unwind_idx *origin;
const struct unwind_idx *stop;
unsigned long begin_addr; unsigned long begin_addr;
unsigned long end_addr; unsigned long end_addr;
}; };
...@@ -49,15 +50,6 @@ extern struct unwind_table *unwind_table_add(unsigned long start, ...@@ -49,15 +50,6 @@ extern struct unwind_table *unwind_table_add(unsigned long start,
extern void unwind_table_del(struct unwind_table *tab); extern void unwind_table_del(struct unwind_table *tab);
extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk); extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk);
#ifdef CONFIG_ARM_UNWIND
extern int __init unwind_init(void);
#else
static inline int __init unwind_init(void)
{
return 0;
}
#endif
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#ifdef CONFIG_ARM_UNWIND #ifdef CONFIG_ARM_UNWIND
......
...@@ -640,6 +640,9 @@ static struct platform_device_id armpmu_plat_device_ids[] = { ...@@ -640,6 +640,9 @@ static struct platform_device_id armpmu_plat_device_ids[] = {
static int __devinit armpmu_device_probe(struct platform_device *pdev) static int __devinit armpmu_device_probe(struct platform_device *pdev)
{ {
if (!cpu_pmu)
return -ENODEV;
cpu_pmu->plat_device = pdev; cpu_pmu->plat_device = pdev;
return 0; return 0;
} }
......
...@@ -895,8 +895,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -895,8 +895,6 @@ void __init setup_arch(char **cmdline_p)
{ {
struct machine_desc *mdesc; struct machine_desc *mdesc;
unwind_init();
setup_processor(); setup_processor();
mdesc = setup_machine_fdt(__atags_pointer); mdesc = setup_machine_fdt(__atags_pointer);
if (!mdesc) if (!mdesc)
...@@ -904,6 +902,12 @@ void __init setup_arch(char **cmdline_p) ...@@ -904,6 +902,12 @@ void __init setup_arch(char **cmdline_p)
machine_desc = mdesc; machine_desc = mdesc;
machine_name = mdesc->name; machine_name = mdesc->name;
#ifdef CONFIG_ZONE_DMA
if (mdesc->dma_zone_size) {
extern unsigned long arm_dma_zone_size;
arm_dma_zone_size = mdesc->dma_zone_size;
}
#endif
if (mdesc->soft_reboot) if (mdesc->soft_reboot)
reboot_setup("s"); reboot_setup("s");
...@@ -934,12 +938,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -934,12 +938,6 @@ void __init setup_arch(char **cmdline_p)
tcm_init(); tcm_init();
#ifdef CONFIG_ZONE_DMA
if (mdesc->dma_zone_size) {
extern unsigned long arm_dma_zone_size;
arm_dma_zone_size = mdesc->dma_zone_size;
}
#endif
#ifdef CONFIG_MULTI_IRQ_HANDLER #ifdef CONFIG_MULTI_IRQ_HANDLER
handle_arch_irq = mdesc->handle_irq; handle_arch_irq = mdesc->handle_irq;
#endif #endif
......
...@@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); ...@@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
struct unwind_ctrl_block { struct unwind_ctrl_block {
unsigned long vrs[16]; /* virtual register set */ unsigned long vrs[16]; /* virtual register set */
unsigned long *insn; /* pointer to the current instructions word */ const unsigned long *insn; /* pointer to the current instructions word */
int entries; /* number of entries left to interpret */ int entries; /* number of entries left to interpret */
int byte; /* current byte number in the instructions word */ int byte; /* current byte number in the instructions word */
}; };
...@@ -83,8 +83,9 @@ enum regs { ...@@ -83,8 +83,9 @@ enum regs {
PC = 15 PC = 15
}; };
extern struct unwind_idx __start_unwind_idx[]; extern const struct unwind_idx __start_unwind_idx[];
extern struct unwind_idx __stop_unwind_idx[]; static const struct unwind_idx *__origin_unwind_idx;
extern const struct unwind_idx __stop_unwind_idx[];
static DEFINE_SPINLOCK(unwind_lock); static DEFINE_SPINLOCK(unwind_lock);
static LIST_HEAD(unwind_tables); static LIST_HEAD(unwind_tables);
...@@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables); ...@@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables);
}) })
/* /*
* Binary search in the unwind index. The entries entries are * Binary search in the unwind index. The entries are
* guaranteed to be sorted in ascending order by the linker. * guaranteed to be sorted in ascending order by the linker.
*
* start = first entry
* origin = first entry with positive offset (or stop if there is no such entry)
* stop - 1 = last entry
*/ */
static struct unwind_idx *search_index(unsigned long addr, static const struct unwind_idx *search_index(unsigned long addr,
struct unwind_idx *first, const struct unwind_idx *start,
struct unwind_idx *last) const struct unwind_idx *origin,
const struct unwind_idx *stop)
{ {
pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last); unsigned long addr_prel31;
pr_debug("%s(%08lx, %p, %p, %p)\n",
__func__, addr, start, origin, stop);
/*
* only search in the section with the matching sign. This way the
* prel31 numbers can be compared as unsigned longs.
*/
if (addr < (unsigned long)start)
/* negative offsets: [start; origin) */
stop = origin;
else
/* positive offsets: [origin; stop) */
start = origin;
/* prel31 for address relavive to start */
addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
while (start < stop - 1) {
const struct unwind_idx *mid = start + ((stop - start) >> 1);
if (addr < first->addr) { /*
* As addr_prel31 is relative to start an offset is needed to
* make it relative to mid.
*/
if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
mid->addr_offset)
stop = mid;
else {
/* keep addr_prel31 relative to start */
addr_prel31 -= ((unsigned long)mid -
(unsigned long)start);
start = mid;
}
}
if (likely(start->addr_offset <= addr_prel31))
return start;
else {
pr_warning("unwind: Unknown symbol address %08lx\n", addr); pr_warning("unwind: Unknown symbol address %08lx\n", addr);
return NULL; return NULL;
} else if (addr >= last->addr) }
return last; }
while (first < last - 1) { static const struct unwind_idx *unwind_find_origin(
struct unwind_idx *mid = first + ((last - first + 1) >> 1); const struct unwind_idx *start, const struct unwind_idx *stop)
{
pr_debug("%s(%p, %p)\n", __func__, start, stop);
while (start < stop - 1) {
const struct unwind_idx *mid = start + ((stop - start) >> 1);
if (addr < mid->addr) if (mid->addr_offset >= 0x40000000)
last = mid; /* negative offset */
start = mid;
else else
first = mid; /* positive offset */
stop = mid;
} }
pr_debug("%s -> %p\n", __func__, stop);
return first; return stop;
} }
static struct unwind_idx *unwind_find_idx(unsigned long addr) static const struct unwind_idx *unwind_find_idx(unsigned long addr)
{ {
struct unwind_idx *idx = NULL; const struct unwind_idx *idx = NULL;
unsigned long flags; unsigned long flags;
pr_debug("%s(%08lx)\n", __func__, addr); pr_debug("%s(%08lx)\n", __func__, addr);
if (core_kernel_text(addr)) if (core_kernel_text(addr)) {
if (unlikely(!__origin_unwind_idx))
__origin_unwind_idx =
unwind_find_origin(__start_unwind_idx,
__stop_unwind_idx);
/* main unwind table */ /* main unwind table */
idx = search_index(addr, __start_unwind_idx, idx = search_index(addr, __start_unwind_idx,
__stop_unwind_idx - 1); __origin_unwind_idx,
else { __stop_unwind_idx);
} else {
/* module unwind tables */ /* module unwind tables */
struct unwind_table *table; struct unwind_table *table;
...@@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr) ...@@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr)
if (addr >= table->begin_addr && if (addr >= table->begin_addr &&
addr < table->end_addr) { addr < table->end_addr) {
idx = search_index(addr, table->start, idx = search_index(addr, table->start,
table->stop - 1); table->origin,
table->stop);
/* Move-to-front to exploit common traces */ /* Move-to-front to exploit common traces */
list_move(&table->list, &unwind_tables); list_move(&table->list, &unwind_tables);
break; break;
...@@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) ...@@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
int unwind_frame(struct stackframe *frame) int unwind_frame(struct stackframe *frame)
{ {
unsigned long high, low; unsigned long high, low;
struct unwind_idx *idx; const struct unwind_idx *idx;
struct unwind_ctrl_block ctrl; struct unwind_ctrl_block ctrl;
/* only go to a higher address on the stack */ /* only go to a higher address on the stack */
...@@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, ...@@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
unsigned long text_size) unsigned long text_size)
{ {
unsigned long flags; unsigned long flags;
struct unwind_idx *idx;
struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
...@@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, ...@@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
if (!tab) if (!tab)
return tab; return tab;
tab->start = (struct unwind_idx *)start; tab->start = (const struct unwind_idx *)start;
tab->stop = (struct unwind_idx *)(start + size); tab->stop = (const struct unwind_idx *)(start + size);
tab->origin = unwind_find_origin(tab->start, tab->stop);
tab->begin_addr = text_addr; tab->begin_addr = text_addr;
tab->end_addr = text_addr + text_size; tab->end_addr = text_addr + text_size;
/* Convert the symbol addresses to absolute values */
for (idx = tab->start; idx < tab->stop; idx++)
idx->addr = prel31_to_addr(&idx->addr);
spin_lock_irqsave(&unwind_lock, flags); spin_lock_irqsave(&unwind_lock, flags);
list_add_tail(&tab->list, &unwind_tables); list_add_tail(&tab->list, &unwind_tables);
spin_unlock_irqrestore(&unwind_lock, flags); spin_unlock_irqrestore(&unwind_lock, flags);
...@@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_table *tab) ...@@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_table *tab)
kfree(tab); kfree(tab);
} }
int __init unwind_init(void)
{
struct unwind_idx *idx;
/* Convert the symbol addresses to absolute values */
for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
idx->addr = prel31_to_addr(&idx->addr);
pr_debug("unwind: ARM stack unwinding initialised\n");
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment