Archived
14
0
Fork 0
* '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
This commit is contained in:
Linus Torvalds 2011-12-13 09:28:23 -08:00
commit 442ee5a942
5 changed files with 101 additions and 68 deletions

View file

@ -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.

View file

@ -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,
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

View file

@ -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;
} }

View file

@ -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)
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)
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

View file

@ -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 {
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);
}) })
/* /*
* 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;
if (addr < first->addr) { pr_debug("%s(%08lx, %p, %p, %p)\n",
pr_warning("unwind: Unknown symbol address %08lx\n", addr); __func__, addr, start, origin, stop);
return NULL;
} else if (addr >= last->addr)
return last;
while (first < last - 1) { /*
struct unwind_idx *mid = first + ((last - first + 1) >> 1); * 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;
if (addr < mid->addr) /* prel31 for address relavive to start */
last = mid; addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
else
first = mid; while (start < stop - 1) {
const struct unwind_idx *mid = start + ((stop - start) >> 1);
/*
* 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;
}
} }
return first; if (likely(start->addr_offset <= addr_prel31))
return start;
else {
pr_warning("unwind: Unknown symbol address %08lx\n", addr);
return NULL;
}
} }
static struct unwind_idx *unwind_find_idx(unsigned long addr) static const struct unwind_idx *unwind_find_origin(
const struct unwind_idx *start, const struct unwind_idx *stop)
{ {
struct unwind_idx *idx = NULL; pr_debug("%s(%p, %p)\n", __func__, start, stop);
while (start < stop - 1) {
const struct unwind_idx *mid = start + ((stop - start) >> 1);
if (mid->addr_offset >= 0x40000000)
/* negative offset */
start = mid;
else
/* positive offset */
stop = mid;
}
pr_debug("%s -> %p\n", __func__, stop);
return stop;
}
static const struct unwind_idx *unwind_find_idx(unsigned long addr)
{
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)
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)
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,
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,
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)
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;
}