diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index f32ce5419573..397b81593142 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -468,6 +468,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: - set the power.irq_safe flag for the device, causing the runtime-PM callbacks to be invoked with interrupts off + bool pm_runtime_is_irq_safe(struct device *dev); + - return true if power.irq_safe flag was set for the device, causing + the runtime-PM callbacks to be invoked with interrupts off + void pm_runtime_mark_last_busy(struct device *dev); - set the power.last_busy field to the current time diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 89c4b5ccc68d..622e364f7711 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -702,7 +702,9 @@ config ARCH_SA1100 select CPU_SA1100 select GENERIC_CLOCKEVENTS select HAVE_IDE + select IRQ_DOMAIN select ISA + select MULTI_IRQ_HANDLER select NEED_MACH_MEMORY_H select SPARSE_IRQ help diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index e57d7e5bf96a..7b69c5f9cd74 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -282,8 +282,8 @@ static int sa1111_retrigger_lowirq(struct irq_data *d) } if (i == 8) - printk(KERN_ERR "Danger Will Robinson: failed to " - "re-trigger IRQ%d\n", d->irq); + pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", + d->irq); return i == 8 ? -1 : 0; } @@ -384,8 +384,8 @@ static int sa1111_retrigger_highirq(struct irq_data *d) } if (i == 8) - printk(KERN_ERR "Danger Will Robinson: failed to " - "re-trigger IRQ%d\n", d->irq); + pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", + d->irq); return i == 8 ? -1 : 0; } @@ -740,9 +740,8 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) goto err_unmap; } - printk(KERN_INFO "SA1111 Microprocessor Companion Chip: " - "silicon revision %lx, metal revision %lx\n", - (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); + pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n", + (id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK); /* * We found it. Wake the chip up, and initialise. diff --git a/arch/arm/include/asm/hw_irq.h b/arch/arm/include/asm/hw_irq.h index a71b417b1856..af79da40af2a 100644 --- a/arch/arm/include/asm/hw_irq.h +++ b/arch/arm/include/asm/hw_irq.h @@ -8,6 +8,7 @@ static inline void ack_bad_irq(int irq) { extern unsigned long irq_err_count; irq_err_count++; + pr_crit("unexpected IRQ trap at vector %02x\n", irq); } void set_irq_flags(unsigned int irq, unsigned int flags); diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h index d428e386c88e..3446f6a1d9fa 100644 --- a/arch/arm/include/asm/mcpm.h +++ b/arch/arm/include/asm/mcpm.h @@ -219,6 +219,23 @@ void __mcpm_outbound_leave_critical(unsigned int cluster, int state); bool __mcpm_outbound_enter_critical(unsigned int this_cpu, unsigned int cluster); int __mcpm_cluster_state(unsigned int cluster); +/** + * mcpm_sync_init - Initialize the cluster synchronization support + * + * @power_up_setup: platform specific function invoked during very + * early CPU/cluster bringup stage. + * + * This prepares memory used by vlocks and the MCPM state machine used + * across CPUs that may have their caches active or inactive. Must be + * called only after a successful call to mcpm_platform_register(). + * + * The power_up_setup argument is a pointer to assembly code called when + * the MMU and caches are still disabled during boot and no stack space is + * available. The affinity level passed to that code corresponds to the + * resource that needs to be initialized (e.g. 1 for cluster level, 0 for + * CPU level). Proper exclusion mechanisms are already activated at that + * point. + */ int __init mcpm_sync_init( void (*power_up_setup)(unsigned int affinity_level)); diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h index 209e6504922e..a89b4076cde4 100644 --- a/arch/arm/include/asm/percpu.h +++ b/arch/arm/include/asm/percpu.h @@ -30,14 +30,14 @@ static inline void set_my_cpu_offset(unsigned long off) static inline unsigned long __my_cpu_offset(void) { unsigned long off; - register unsigned long *sp asm ("sp"); /* * Read TPIDRPRW. * We want to allow caching the value, so avoid using volatile and * instead use a fake stack read to hazard against barrier(). */ - asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp)); + asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) + : "Q" (*(const unsigned long *)current_stack_pointer)); return off; } diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 78a779361682..19cfab526d13 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -157,7 +157,15 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) { - __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); + extern pmdval_t user_pmd_table; + pmdval_t prot; + + if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE)) + prot = user_pmd_table; + else + prot = _PAGE_USER_TABLE; + + __pmd_populate(pmdp, page_to_phys(ptep), prot); } #define pmd_pgtable(pmd) pmd_page(pmd) diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h index 5cfba15cb401..5e68278e953e 100644 --- a/arch/arm/include/asm/pgtable-2level-hwdef.h +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h @@ -20,12 +20,14 @@ #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) +#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ /* * - section */ +#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index 9fd61c72a33a..f8f1cff62065 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -76,6 +76,7 @@ #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ +#define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */ #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ /* diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 3b30062975b2..d5cac545ba33 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -252,17 +252,57 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, set_pte_ext(ptep, pteval, ext); } -#define PTE_BIT_FUNC(fn,op) \ -static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } +static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) +{ + pte_val(pte) &= ~pgprot_val(prot); + return pte; +} -PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY); -PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY); -PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); -PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); -PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); -PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); -PTE_BIT_FUNC(mkexec, &= ~L_PTE_XN); -PTE_BIT_FUNC(mknexec, |= L_PTE_XN); +static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot) +{ + pte_val(pte) |= pgprot_val(prot); + return pte; +} + +static inline pte_t pte_wrprotect(pte_t pte) +{ + return set_pte_bit(pte, __pgprot(L_PTE_RDONLY)); +} + +static inline pte_t pte_mkwrite(pte_t pte) +{ + return clear_pte_bit(pte, __pgprot(L_PTE_RDONLY)); +} + +static inline pte_t pte_mkclean(pte_t pte) +{ + return clear_pte_bit(pte, __pgprot(L_PTE_DIRTY)); +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + return set_pte_bit(pte, __pgprot(L_PTE_DIRTY)); +} + +static inline pte_t pte_mkold(pte_t pte) +{ + return clear_pte_bit(pte, __pgprot(L_PTE_YOUNG)); +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + return set_pte_bit(pte, __pgprot(L_PTE_YOUNG)); +} + +static inline pte_t pte_mkexec(pte_t pte) +{ + return clear_pte_bit(pte, __pgprot(L_PTE_XN)); +} + +static inline pte_t pte_mknexec(pte_t pte) +{ + return set_pte_bit(pte, __pgprot(L_PTE_XN)); +} static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 601264d983fa..51622ba7c4a6 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -154,9 +154,8 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) return regs->ARM_sp; } -#define current_pt_regs(void) ({ \ - register unsigned long sp asm ("sp"); \ - (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \ +#define current_pt_regs(void) ({ (struct pt_regs *) \ + ((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \ }) #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index ce73ab635414..d890e41f5520 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -89,6 +89,11 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) +/* + * how to get the current stack pointer in C + */ +register unsigned long current_stack_pointer asm ("sp"); + /* * how to get the thread information struct from C */ @@ -96,8 +101,8 @@ static inline struct thread_info *current_thread_info(void) __attribute_const__; static inline struct thread_info *current_thread_info(void) { - register unsigned long sp asm ("sp"); - return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); + return (struct thread_info *) + (current_stack_pointer & ~(THREAD_SIZE - 1)); } #define thread_saved_pc(tsk) \ diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h index f4ab34fd4f72..ee5f3084243c 100644 --- a/arch/arm/include/asm/vfp.h +++ b/arch/arm/include/asm/vfp.h @@ -22,6 +22,7 @@ #define FPSID_NODOUBLE (1<<20) #define FPSID_ARCH_BIT (16) #define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define FPSID_CPUID_ARCH_MASK (0x7F << FPSID_ARCH_BIT) #define FPSID_PART_BIT (8) #define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) #define FPSID_VARIANT_BIT (4) @@ -75,6 +76,10 @@ /* MVFR0 bits */ #define MVFR0_A_SIMD_BIT (0) #define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) +#define MVFR0_SP_BIT (4) +#define MVFR0_SP_MASK (0xf << MVFR0_SP_BIT) +#define MVFR0_DP_BIT (8) +#define MVFR0_DP_MASK (0xf << MVFR0_DP_BIT) /* Bit patterns for decoding the packaged operation descriptors */ #define VFPOPDESC_LENGTH_BIT (9) diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 38ddd9f83d0e..64886387c0bf 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -47,6 +47,7 @@ endif obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o +obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o @@ -84,6 +85,7 @@ obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o obj-$(CONFIG_IWMMXT) += iwmmxt.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o +CFLAGS_pj4-cp0.o := -marm AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o diff --git a/arch/arm/kernel/atags_compat.c b/arch/arm/kernel/atags_compat.c index 5236ad38f417..05c28b12353c 100644 --- a/arch/arm/kernel/atags_compat.c +++ b/arch/arm/kernel/atags_compat.c @@ -97,8 +97,7 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) struct tag *tag = taglist; if (params->u1.s.page_size != PAGE_SIZE) { - printk(KERN_WARNING "Warning: bad configuration page, " - "trying to continue\n"); + pr_warn("Warning: bad configuration page, trying to continue\n"); return; } @@ -109,8 +108,7 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) params->u1.s.nr_pages != 0x04000 && params->u1.s.nr_pages != 0x08000 && params->u1.s.nr_pages != 0x10000) { - printk(KERN_WARNING "Warning: bad NeTTrom parameters " - "detected, using defaults\n"); + pr_warn("Warning: bad NeTTrom parameters detected, using defaults\n"); params->u1.s.nr_pages = 0x1000; /* 16MB */ params->u1.s.ramdisk_size = 0; diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 528f8af2addb..68c6ae0b9e4c 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c @@ -167,8 +167,7 @@ static void __init parse_tags(const struct tag *t) { for (; t->hdr.size; t = tag_next(t)) if (!parse_tag(t)) - printk(KERN_WARNING - "Ignoring unrecognised tag 0x%08x\n", + pr_warn("Ignoring unrecognised tag 0x%08x\n", t->hdr.tag); } @@ -193,7 +192,7 @@ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) */ for_each_machine_desc(p) if (machine_nr == p->nr) { - printk("Machine: %s\n", p->name); + pr_info("Machine: %s\n", p->name); mdesc = p; break; } diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c index c7ff8073416f..5a3379055f55 100644 --- a/arch/arm/kernel/atags_proc.c +++ b/arch/arm/kernel/atags_proc.c @@ -41,7 +41,7 @@ static int __init init_atags_procfs(void) size_t size; if (tag->hdr.tag != ATAG_CORE) { - printk(KERN_INFO "No ATAGs?"); + pr_info("No ATAGs?"); return -EINVAL; } @@ -68,7 +68,7 @@ static int __init init_atags_procfs(void) nomem: kfree(b); - printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); + pr_err("Exporting ATAGs: not enough memory\n"); return -ENOMEM; } diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 17a26c17f7f5..391ffdfce571 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -355,7 +355,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) /* * Report what we did for this bus */ - printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", + pr_info("PCI: bus%d: Fast back to back transfers %sabled\n", bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); } EXPORT_SYMBOL(pcibios_fixup_bus); diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 360bb6d701f5..84363fe7bad2 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c @@ -213,8 +213,8 @@ void __init isa_init_dma(void) for (chan = 0; chan < 8; chan++) { int ret = isa_dma_add(chan, &isa_dma[chan]); if (ret) - printk(KERN_ERR "ISADMA%u: unable to register: %d\n", - chan, ret); + pr_err("ISADMA%u: unable to register: %d\n", + chan, ret); } request_dma(DMA_ISA_CASCADE, "cascade"); diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 7b829d9663b1..e651c4d0a0d9 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -79,7 +79,7 @@ int request_dma(unsigned int chan, const char *device_id) return ret; bad_dma: - printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan); + pr_err("dma: trying to allocate DMA%d\n", chan); return -EINVAL; busy: @@ -100,7 +100,7 @@ void free_dma(unsigned int chan) goto bad_dma; if (dma->active) { - printk(KERN_ERR "dma%d: freeing active DMA\n", chan); + pr_err("dma%d: freeing active DMA\n", chan); dma->d_ops->disable(chan, dma); dma->active = 0; } @@ -111,11 +111,11 @@ void free_dma(unsigned int chan) return; } - printk(KERN_ERR "dma%d: trying to free free DMA\n", chan); + pr_err("dma%d: trying to free free DMA\n", chan); return; bad_dma: - printk(KERN_ERR "dma: trying to free DMA%d\n", chan); + pr_err("dma: trying to free DMA%d\n", chan); } EXPORT_SYMBOL(free_dma); @@ -126,8 +126,7 @@ void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) dma_t *dma = dma_channel(chan); if (dma->active) - printk(KERN_ERR "dma%d: altering DMA SG while " - "DMA active\n", chan); + pr_err("dma%d: altering DMA SG while DMA active\n", chan); dma->sg = sg; dma->sgcount = nr_sg; @@ -144,8 +143,7 @@ void __set_dma_addr (unsigned int chan, void *addr) dma_t *dma = dma_channel(chan); if (dma->active) - printk(KERN_ERR "dma%d: altering DMA address while " - "DMA active\n", chan); + pr_err("dma%d: altering DMA address while DMA active\n", chan); dma->sg = NULL; dma->addr = addr; @@ -162,8 +160,7 @@ void set_dma_count (unsigned int chan, unsigned long count) dma_t *dma = dma_channel(chan); if (dma->active) - printk(KERN_ERR "dma%d: altering DMA count while " - "DMA active\n", chan); + pr_err("dma%d: altering DMA count while DMA active\n", chan); dma->sg = NULL; dma->count = count; @@ -178,8 +175,7 @@ void set_dma_mode (unsigned int chan, unsigned int mode) dma_t *dma = dma_channel(chan); if (dma->active) - printk(KERN_ERR "dma%d: altering DMA mode while " - "DMA active\n", chan); + pr_err("dma%d: altering DMA mode while DMA active\n", chan); dma->dma_mode = mode; dma->invalid = 1; @@ -202,7 +198,7 @@ void enable_dma (unsigned int chan) return; free_dma: - printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan); + pr_err("dma%d: trying to enable free DMA\n", chan); BUG(); } EXPORT_SYMBOL(enable_dma); @@ -223,7 +219,7 @@ void disable_dma (unsigned int chan) return; free_dma: - printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan); + pr_err("dma%d: trying to disable free DMA\n", chan); BUG(); } EXPORT_SYMBOL(disable_dma); @@ -240,7 +236,7 @@ EXPORT_SYMBOL(dma_channel_active); void set_dma_page(unsigned int chan, char pagenr) { - printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan); + pr_err("dma%d: trying to set_dma_page\n", chan); } EXPORT_SYMBOL(set_dma_page); diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 6bb09d4abdea..f8ccc21fa032 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -109,241 +109,6 @@ ENDPROC(ret_from_fork) #undef CALL #define CALL(x) .long x -#ifdef CONFIG_FUNCTION_TRACER -/* - * When compiling with -pg, gcc inserts a call to the mcount routine at the - * start of every function. In mcount, apart from the function's address (in - * lr), we need to get hold of the function's caller's address. - * - * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: - * - * bl mcount - * - * These versions have the limitation that in order for the mcount routine to - * be able to determine the function's caller's address, an APCS-style frame - * pointer (which is set up with something like the code below) is required. - * - * mov ip, sp - * push {fp, ip, lr, pc} - * sub fp, ip, #4 - * - * With EABI, these frame pointers are not available unless -mapcs-frame is - * specified, and if building as Thumb-2, not even then. - * - * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, - * with call sites like: - * - * push {lr} - * bl __gnu_mcount_nc - * - * With these compilers, frame pointers are not necessary. - * - * mcount can be thought of as a function called in the middle of a subroutine - * call. As such, it needs to be transparent for both the caller and the - * callee: the original lr needs to be restored when leaving mcount, and no - * registers should be clobbered. (In the __gnu_mcount_nc implementation, we - * clobber the ip register. This is OK because the ARM calling convention - * allows it to be clobbered in subroutines and doesn't use it to hold - * parameters.) - * - * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" - * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see - * arch/arm/kernel/ftrace.c). - */ - -#ifndef CONFIG_OLD_MCOUNT -#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) -#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. -#endif -#endif - -.macro mcount_adjust_addr rd, rn - bic \rd, \rn, #1 @ clear the Thumb bit if present - sub \rd, \rd, #MCOUNT_INSN_SIZE -.endm - -.macro __mcount suffix - mcount_enter - ldr r0, =ftrace_trace_function - ldr r2, [r0] - adr r0, .Lftrace_stub - cmp r0, r2 - bne 1f - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - ldr r1, =ftrace_graph_return - ldr r2, [r1] - cmp r0, r2 - bne ftrace_graph_caller\suffix - - ldr r1, =ftrace_graph_entry - ldr r2, [r1] - ldr r0, =ftrace_graph_entry_stub - cmp r0, r2 - bne ftrace_graph_caller\suffix -#endif - - mcount_exit - -1: mcount_get_lr r1 @ lr of instrumented func - mcount_adjust_addr r0, lr @ instrumented function - adr lr, BSYM(2f) - mov pc, r2 -2: mcount_exit -.endm - -.macro __ftrace_caller suffix - mcount_enter - - mcount_get_lr r1 @ lr of instrumented func - mcount_adjust_addr r0, lr @ instrumented function - - .globl ftrace_call\suffix -ftrace_call\suffix: - bl ftrace_stub - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - .globl ftrace_graph_call\suffix -ftrace_graph_call\suffix: - mov r0, r0 -#endif - - mcount_exit -.endm - -.macro __ftrace_graph_caller - sub r0, fp, #4 @ &lr of instrumented routine (&parent) -#ifdef CONFIG_DYNAMIC_FTRACE - @ called from __ftrace_caller, saved in mcount_enter - ldr r1, [sp, #16] @ instrumented routine (func) - mcount_adjust_addr r1, r1 -#else - @ called from __mcount, untouched in lr - mcount_adjust_addr r1, lr @ instrumented routine (func) -#endif - mov r2, fp @ frame pointer - bl prepare_ftrace_return - mcount_exit -.endm - -#ifdef CONFIG_OLD_MCOUNT -/* - * mcount - */ - -.macro mcount_enter - stmdb sp!, {r0-r3, lr} -.endm - -.macro mcount_get_lr reg - ldr \reg, [fp, #-4] -.endm - -.macro mcount_exit - ldr lr, [fp, #-4] - ldmia sp!, {r0-r3, pc} -.endm - -ENTRY(mcount) -#ifdef CONFIG_DYNAMIC_FTRACE - stmdb sp!, {lr} - ldr lr, [fp, #-4] - ldmia sp!, {pc} -#else - __mcount _old -#endif -ENDPROC(mcount) - -#ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(ftrace_caller_old) - __ftrace_caller _old -ENDPROC(ftrace_caller_old) -#endif - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -ENTRY(ftrace_graph_caller_old) - __ftrace_graph_caller -ENDPROC(ftrace_graph_caller_old) -#endif - -.purgem mcount_enter -.purgem mcount_get_lr -.purgem mcount_exit -#endif - -/* - * __gnu_mcount_nc - */ - -.macro mcount_enter -/* - * This pad compensates for the push {lr} at the call site. Note that we are - * unable to unwind through a function which does not otherwise save its lr. - */ - UNWIND(.pad #4) - stmdb sp!, {r0-r3, lr} - UNWIND(.save {r0-r3, lr}) -.endm - -.macro mcount_get_lr reg - ldr \reg, [sp, #20] -.endm - -.macro mcount_exit - ldmia sp!, {r0-r3, ip, lr} - ret ip -.endm - -ENTRY(__gnu_mcount_nc) -UNWIND(.fnstart) -#ifdef CONFIG_DYNAMIC_FTRACE - mov ip, lr - ldmia sp!, {lr} - ret ip -#else - __mcount -#endif -UNWIND(.fnend) -ENDPROC(__gnu_mcount_nc) - -#ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(ftrace_caller) -UNWIND(.fnstart) - __ftrace_caller -UNWIND(.fnend) -ENDPROC(ftrace_caller) -#endif - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -ENTRY(ftrace_graph_caller) -UNWIND(.fnstart) - __ftrace_graph_caller -UNWIND(.fnend) -ENDPROC(ftrace_graph_caller) -#endif - -.purgem mcount_enter -.purgem mcount_get_lr -.purgem mcount_exit - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - .globl return_to_handler -return_to_handler: - stmdb sp!, {r0-r3} - mov r0, fp @ frame pointer - bl ftrace_return_to_handler - mov lr, r0 @ r0 has real ret addr - ldmia sp!, {r0-r3} - ret lr -#endif - -ENTRY(ftrace_stub) -.Lftrace_stub: - ret lr -ENDPROC(ftrace_stub) - -#endif /* CONFIG_FUNCTION_TRACER */ - /*============================================================================= * SWI handler *----------------------------------------------------------------------------- diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S new file mode 100644 index 000000000000..fe57c73e70a4 --- /dev/null +++ b/arch/arm/kernel/entry-ftrace.S @@ -0,0 +1,243 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "entry-header.S" + +/* + * When compiling with -pg, gcc inserts a call to the mcount routine at the + * start of every function. In mcount, apart from the function's address (in + * lr), we need to get hold of the function's caller's address. + * + * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: + * + * bl mcount + * + * These versions have the limitation that in order for the mcount routine to + * be able to determine the function's caller's address, an APCS-style frame + * pointer (which is set up with something like the code below) is required. + * + * mov ip, sp + * push {fp, ip, lr, pc} + * sub fp, ip, #4 + * + * With EABI, these frame pointers are not available unless -mapcs-frame is + * specified, and if building as Thumb-2, not even then. + * + * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, + * with call sites like: + * + * push {lr} + * bl __gnu_mcount_nc + * + * With these compilers, frame pointers are not necessary. + * + * mcount can be thought of as a function called in the middle of a subroutine + * call. As such, it needs to be transparent for both the caller and the + * callee: the original lr needs to be restored when leaving mcount, and no + * registers should be clobbered. (In the __gnu_mcount_nc implementation, we + * clobber the ip register. This is OK because the ARM calling convention + * allows it to be clobbered in subroutines and doesn't use it to hold + * parameters.) + * + * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" + * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see + * arch/arm/kernel/ftrace.c). + */ + +#ifndef CONFIG_OLD_MCOUNT +#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) +#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. +#endif +#endif + +.macro mcount_adjust_addr rd, rn + bic \rd, \rn, #1 @ clear the Thumb bit if present + sub \rd, \rd, #MCOUNT_INSN_SIZE +.endm + +.macro __mcount suffix + mcount_enter + ldr r0, =ftrace_trace_function + ldr r2, [r0] + adr r0, .Lftrace_stub + cmp r0, r2 + bne 1f + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + ldr r1, =ftrace_graph_return + ldr r2, [r1] + cmp r0, r2 + bne ftrace_graph_caller\suffix + + ldr r1, =ftrace_graph_entry + ldr r2, [r1] + ldr r0, =ftrace_graph_entry_stub + cmp r0, r2 + bne ftrace_graph_caller\suffix +#endif + + mcount_exit + +1: mcount_get_lr r1 @ lr of instrumented func + mcount_adjust_addr r0, lr @ instrumented function + adr lr, BSYM(2f) + mov pc, r2 +2: mcount_exit +.endm + +.macro __ftrace_caller suffix + mcount_enter + + mcount_get_lr r1 @ lr of instrumented func + mcount_adjust_addr r0, lr @ instrumented function + + .globl ftrace_call\suffix +ftrace_call\suffix: + bl ftrace_stub + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_call\suffix +ftrace_graph_call\suffix: + mov r0, r0 +#endif + + mcount_exit +.endm + +.macro __ftrace_graph_caller + sub r0, fp, #4 @ &lr of instrumented routine (&parent) +#ifdef CONFIG_DYNAMIC_FTRACE + @ called from __ftrace_caller, saved in mcount_enter + ldr r1, [sp, #16] @ instrumented routine (func) + mcount_adjust_addr r1, r1 +#else + @ called from __mcount, untouched in lr + mcount_adjust_addr r1, lr @ instrumented routine (func) +#endif + mov r2, fp @ frame pointer + bl prepare_ftrace_return + mcount_exit +.endm + +#ifdef CONFIG_OLD_MCOUNT +/* + * mcount + */ + +.macro mcount_enter + stmdb sp!, {r0-r3, lr} +.endm + +.macro mcount_get_lr reg + ldr \reg, [fp, #-4] +.endm + +.macro mcount_exit + ldr lr, [fp, #-4] + ldmia sp!, {r0-r3, pc} +.endm + +ENTRY(mcount) +#ifdef CONFIG_DYNAMIC_FTRACE + stmdb sp!, {lr} + ldr lr, [fp, #-4] + ldmia sp!, {pc} +#else + __mcount _old +#endif +ENDPROC(mcount) + +#ifdef CONFIG_DYNAMIC_FTRACE +ENTRY(ftrace_caller_old) + __ftrace_caller _old +ENDPROC(ftrace_caller_old) +#endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(ftrace_graph_caller_old) + __ftrace_graph_caller +ENDPROC(ftrace_graph_caller_old) +#endif + +.purgem mcount_enter +.purgem mcount_get_lr +.purgem mcount_exit +#endif + +/* + * __gnu_mcount_nc + */ + +.macro mcount_enter +/* + * This pad compensates for the push {lr} at the call site. Note that we are + * unable to unwind through a function which does not otherwise save its lr. + */ + UNWIND(.pad #4) + stmdb sp!, {r0-r3, lr} + UNWIND(.save {r0-r3, lr}) +.endm + +.macro mcount_get_lr reg + ldr \reg, [sp, #20] +.endm + +.macro mcount_exit + ldmia sp!, {r0-r3, ip, lr} + ret ip +.endm + +ENTRY(__gnu_mcount_nc) +UNWIND(.fnstart) +#ifdef CONFIG_DYNAMIC_FTRACE + mov ip, lr + ldmia sp!, {lr} + ret ip +#else + __mcount +#endif +UNWIND(.fnend) +ENDPROC(__gnu_mcount_nc) + +#ifdef CONFIG_DYNAMIC_FTRACE +ENTRY(ftrace_caller) +UNWIND(.fnstart) + __ftrace_caller +UNWIND(.fnend) +ENDPROC(ftrace_caller) +#endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(ftrace_graph_caller) +UNWIND(.fnstart) + __ftrace_graph_caller +UNWIND(.fnend) +ENDPROC(ftrace_graph_caller) +#endif + +.purgem mcount_enter +.purgem mcount_get_lr +.purgem mcount_exit + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl return_to_handler +return_to_handler: + stmdb sp!, {r0-r3} + mov r0, fp @ frame pointer + bl ftrace_return_to_handler + mov lr, r0 @ r0 has real ret addr + ldmia sp!, {r0-r3} + ret lr +#endif + +ENTRY(ftrace_stub) +.Lftrace_stub: + ret lr +ENDPROC(ftrace_stub) diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 131a6ab5f355..8b96972dcb1d 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -213,7 +213,7 @@ static void etm_dump(void) int length; if (!t->etb_regs) { - printk(KERN_INFO "No tracing hardware found\n"); + pr_info("No tracing hardware found\n"); return; } @@ -229,11 +229,11 @@ static void etm_dump(void) etb_writel(t, first, ETBR_READADDR); - printk(KERN_INFO "Trace buffer contents length: %d\n", length); - printk(KERN_INFO "--- ETB buffer begin ---\n"); + pr_info("Trace buffer contents length: %d\n", length); + pr_info("--- ETB buffer begin ---\n"); for (; length; length--) printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); - printk(KERN_INFO "\n--- ETB buffer end ---\n"); + pr_info("\n--- ETB buffer end ---\n"); /* deassert the overflow bit */ etb_writel(t, 1, ETBR_CTRL); @@ -633,14 +633,14 @@ static int __init etm_init(void) retval = amba_driver_register(&etb_driver); if (retval) { - printk(KERN_ERR "Failed to register etb\n"); + pr_err("Failed to register etb\n"); return retval; } retval = amba_driver_register(&etm_driver); if (retval) { amba_driver_unregister(&etb_driver); - printk(KERN_ERR "Failed to probe etm\n"); + pr_err("Failed to probe etm\n"); return retval; } diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index b37752a96652..059c3da0fee3 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -124,7 +124,7 @@ int claim_fiq(struct fiq_handler *f) void release_fiq(struct fiq_handler *f) { if (current_fiq != f) { - printk(KERN_ERR "%s FIQ trying to release %s FIQ\n", + pr_err("%s FIQ trying to release %s FIQ\n", f->name, current_fiq->name); dump_stack(); return; diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index 9203cf883330..eedefe050022 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -51,6 +51,7 @@ void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) from++; } } +EXPORT_SYMBOL(_memcpy_fromio); /* * Copy data from "real" memory space to IO memory space. @@ -66,6 +67,7 @@ void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) to++; } } +EXPORT_SYMBOL(_memcpy_toio); /* * "memset" on IO memory space. @@ -79,7 +81,4 @@ void _memset_io(volatile void __iomem *dst, int c, size_t count) dst++; } } - -EXPORT_SYMBOL(_memcpy_fromio); -EXPORT_SYMBOL(_memcpy_toio); EXPORT_SYMBOL(_memset_io); diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7c81ec428b9b..ad857bada96c 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; if (irq >= nr_irqs) { - printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); + pr_err("Trying to set irq flags for IRQ%d\n", irq); return; } @@ -135,7 +136,6 @@ int __init arch_probe_nr_irqs(void) #endif #ifdef CONFIG_HOTPLUG_CPU - static bool migrate_one_irq(struct irq_desc *desc) { struct irq_data *d = irq_desc_get_irq_data(desc); @@ -187,8 +187,8 @@ void migrate_irqs(void) affinity_broken = migrate_one_irq(desc); raw_spin_unlock(&desc->lock); - if (affinity_broken && printk_ratelimit()) - pr_warn("IRQ%u no longer affine to CPU%u\n", + if (affinity_broken) + pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n", i, smp_processor_id()); } diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index ad58e565fe98..49fadbda8c63 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -58,6 +58,7 @@ #define MMX_SIZE (0x98) .text + .arm /* * Lazy switching of Concan coprocessor context @@ -182,6 +183,8 @@ concan_load: tmcr wCon, r2 ret lr +ENDPROC(iwmmxt_task_enable) + /* * Back up Concan regs to save area and disable access to them * (mainly for gdb or sleep mode usage) @@ -232,6 +235,8 @@ ENTRY(iwmmxt_task_disable) 1: msr cpsr_c, ip @ restore interrupt mode ldmfd sp!, {r4, pc} +ENDPROC(iwmmxt_task_disable) + /* * Copy Concan state to given memory address * @@ -268,6 +273,8 @@ ENTRY(iwmmxt_task_copy) msr cpsr_c, ip @ restore interrupt mode ret r3 +ENDPROC(iwmmxt_task_copy) + /* * Restore Concan state from given memory address * @@ -304,6 +311,8 @@ ENTRY(iwmmxt_task_restore) msr cpsr_c, ip @ restore interrupt mode ret r3 +ENDPROC(iwmmxt_task_restore) + /* * Concan handling on task switch * @@ -335,6 +344,8 @@ ENTRY(iwmmxt_task_switch) mrc p15, 0, r1, c2, c0, 0 sub pc, lr, r1, lsr #32 @ cpwait and return +ENDPROC(iwmmxt_task_switch) + /* * Remove Concan ownership of given task * @@ -353,6 +364,8 @@ ENTRY(iwmmxt_task_release) msr cpsr_c, r2 @ restore interrupts ret lr +ENDPROC(iwmmxt_task_release) + .data concan_owner: .word 0 diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8cf0996aa1a8..4f75192f2ef9 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -126,12 +126,12 @@ void machine_crash_shutdown(struct pt_regs *regs) msecs--; } if (atomic_read(&waiting_for_crash_ipi) > 0) - printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); + pr_warn("Non-crashing CPUs did not react to IPI\n"); crash_save_cpu(regs, smp_processor_id()); machine_kexec_mask_interrupts(); - printk(KERN_INFO "Loading crashdump kernel...\n"); + pr_info("Loading crashdump kernel...\n"); } /* @@ -177,7 +177,7 @@ void machine_kexec(struct kimage *image) reboot_entry_phys = (unsigned long)reboot_entry + (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); - printk(KERN_INFO "Bye!\n"); + pr_info("Bye!\n"); if (kexec_reinit) kexec_reinit(); diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 6a4dffefd357..bea7db9e5b80 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -251,7 +251,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, #endif default: - printk(KERN_ERR "%s: unknown relocation: %u\n", + pr_err("%s: unknown relocation: %u\n", module->name, ELF32_R_TYPE(rel->r_info)); return -ENOEXEC; } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index fe972a2f3df3..fdfa3a78ec8c 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -51,8 +51,8 @@ EXPORT_SYMBOL(__stack_chk_guard); static const char *processor_modes[] __maybe_unused = { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", - "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , - "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" + "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "MON_32" , "ABT_32" , + "UK8_32" , "UK9_32" , "HYP_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" }; static const char *isa_modes[] __maybe_unused = { diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 98ea4b7eb406..24b4a04846eb 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -39,13 +39,12 @@ void *return_address(unsigned int level) { struct return_address_data data; struct stackframe frame; - register unsigned long current_sp asm ("sp"); data.level = level + 2; data.addr = NULL; frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; + frame.sp = current_stack_pointer; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)return_address; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c03106378b49..8361652b6dab 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -900,6 +900,7 @@ void __init setup_arch(char **cmdline_p) mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); machine_desc = mdesc; machine_name = mdesc->name; + dump_stack_set_arch_desc("%s", mdesc->name); if (mdesc->reboot_mode != REBOOT_HARD) reboot_mode = mdesc->reboot_mode; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index bd1983437205..8aa6f1b87c9e 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -592,7 +592,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) } syscall = 0; } else if (thread_flags & _TIF_UPROBE) { - clear_thread_flag(TIF_UPROBE); uprobe_notify_resume(regs); } else { clear_thread_flag(TIF_NOTIFY_RESUME); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 13396d3d600e..5e6052e18850 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -225,7 +225,7 @@ void __cpu_die(unsigned int cpu) pr_err("CPU%u: cpu didn't die\n", cpu); return; } - printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + pr_notice("CPU%u: shutdown\n", cpu); /* * platform_cpu_kill() is generally expected to do the powering off @@ -235,7 +235,7 @@ void __cpu_die(unsigned int cpu) * the requesting CPU and the dying CPU actually losing power. */ if (!platform_cpu_kill(cpu)) - printk("CPU%u: unable to kill\n", cpu); + pr_err("CPU%u: unable to kill\n", cpu); } /* @@ -351,7 +351,7 @@ asmlinkage void secondary_start_kernel(void) cpu_init(); - printk("CPU%u: Booted secondary processor\n", cpu); + pr_debug("CPU%u: Booted secondary processor\n", cpu); preempt_disable(); trace_hardirqs_off(); @@ -387,9 +387,6 @@ asmlinkage void secondary_start_kernel(void) void __init smp_cpus_done(unsigned int max_cpus) { - printk(KERN_INFO "SMP: Total of %d processors activated.\n", - num_online_cpus()); - hyp_mode_check(); } @@ -521,7 +518,7 @@ static void ipi_cpu_stop(unsigned int cpu) if (system_state == SYSTEM_BOOTING || system_state == SYSTEM_RUNNING) { raw_spin_lock(&stop_lock); - printk(KERN_CRIT "CPU%u: stopping\n", cpu); + pr_crit("CPU%u: stopping\n", cpu); dump_stack(); raw_spin_unlock(&stop_lock); } @@ -615,8 +612,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs) break; default: - printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", - cpu, ipinr); + pr_crit("CPU%u: Unknown IPI message 0x%x\n", + cpu, ipinr); break; } diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 93090213c71c..172c6a05d27f 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -199,7 +199,7 @@ static void twd_calibrate_rate(void) * the timer ticks */ if (twd_timer_rate == 0) { - printk(KERN_INFO "Calibrating local timer... "); + pr_info("Calibrating local timer... "); /* Wait for a tick to start */ waitjiffies = get_jiffies_64() + 1; @@ -223,7 +223,7 @@ static void twd_calibrate_rate(void) twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); - printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, + pr_cont("%lu.%02luMHz.\n", twd_timer_rate / 1000000, (twd_timer_rate / 10000) % 100); } } diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index f065eb05d254..92b72375c4c7 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -134,12 +134,10 @@ static noinline void __save_stack_trace(struct task_struct *tsk, frame.pc = thread_saved_pc(tsk); #endif } else { - register unsigned long current_sp asm ("sp"); - /* We don't want this function nor the caller */ data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; + frame.sp = current_stack_pointer; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)__save_stack_trace; } diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 587fdfe1a72c..afdd51e30bec 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -260,7 +260,7 @@ static int __init swp_emulation_init(void) return -ENOMEM; #endif /* CONFIG_PROC_FS */ - printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); + pr_notice("Registering SWP/SWPB emulation handler\n"); register_undef_hook(&swp_hook); return 0; diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c index 80f0d69205e7..8ff8dbfbe9fb 100644 --- a/arch/arm/kernel/thumbee.c +++ b/arch/arm/kernel/thumbee.c @@ -72,7 +72,7 @@ static int __init thumbee_init(void) if ((pfr0 & 0x0000f000) != 0x00001000) return 0; - printk(KERN_INFO "ThumbEE CPU extension supported.\n"); + pr_info("ThumbEE CPU extension supported.\n"); elf_hwcap |= HWCAP_THUMBEE; thread_register_notifier(&thumbee_notifier_block); diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 89cfdd6e50cb..08b7847bf912 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -165,7 +165,7 @@ static void update_cpu_capacity(unsigned int cpu) set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); - printk(KERN_INFO "CPU%u: update cpu_capacity %lu\n", + pr_info("CPU%u: update cpu_capacity %lu\n", cpu, arch_scale_cpu_capacity(NULL, cpu)); } @@ -269,7 +269,7 @@ void store_cpu_topology(unsigned int cpuid) update_cpu_capacity(cpuid); - printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", + pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, cpu_topology[cpuid].core_id, cpu_topology[cpuid].socket_id, mpidr); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 9f5d81881eb6..788e23fe64d8 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -198,14 +198,14 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) } if (!fp) { - printk("no frame pointer"); + pr_cont("no frame pointer"); ok = 0; } else if (verify_stack(fp)) { - printk("invalid frame pointer 0x%08x", fp); + pr_cont("invalid frame pointer 0x%08x", fp); ok = 0; } else if (fp < (unsigned long)end_of_stack(tsk)) - printk("frame pointer underflow"); - printk("\n"); + pr_cont("frame pointer underflow"); + pr_cont("\n"); if (ok) c_backtrace(fp, mode); @@ -240,8 +240,8 @@ static int __die(const char *str, int err, struct pt_regs *regs) static int die_counter; int ret; - printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP - S_ISA "\n", str, err, ++die_counter); + pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP S_ISA "\n", + str, err, ++die_counter); /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); @@ -250,8 +250,8 @@ static int __die(const char *str, int err, struct pt_regs *regs) print_modules(); __show_regs(regs); - printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); + pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", + TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, @@ -446,7 +446,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) die_sig: #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { - printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", + pr_info("%s (%d): undefined instruction: pc=%p\n", current->comm, task_pid_nr(current), pc); __show_regs(regs); dump_instr(KERN_INFO, regs); @@ -496,7 +496,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) { console_verbose(); - printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]); + pr_crit("Bad mode in %s handler detected\n", handler[reason]); die("Oops - bad mode", regs, 0); local_irq_disable(); @@ -516,7 +516,7 @@ static int bad_syscall(int n, struct pt_regs *regs) #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_SYSCALL) { - printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", + pr_err("[%d] %s: obsolete system call %08x.\n", task_pid_nr(current), current->comm, n); dump_instr(KERN_ERR, regs); } @@ -694,7 +694,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) * something catastrophic has happened */ if (user_debug & UDBG_SYSCALL) { - printk("[%d] %s: arm syscall %d\n", + pr_err("[%d] %s: arm syscall %d\n", task_pid_nr(current), current->comm, no); dump_instr("", regs); if (user_mode(regs)) { @@ -753,8 +753,8 @@ late_initcall(arm_mrc_hook_init); void __bad_xchg(volatile void *ptr, int size) { - printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", - __builtin_return_address(0), ptr, size); + pr_err("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", + __builtin_return_address(0), ptr, size); BUG(); } EXPORT_SYMBOL(__bad_xchg); @@ -771,8 +771,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_BADABORT) { - printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n", - task_pid_nr(current), current->comm, code, instr); + pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n", + task_pid_nr(current), current->comm, code, instr); dump_instr(KERN_ERR, regs); show_pte(current->mm, addr); } @@ -788,29 +788,29 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) void __readwrite_bug(const char *fn) { - printk("%s called, but not implemented\n", fn); + pr_err("%s called, but not implemented\n", fn); BUG(); } EXPORT_SYMBOL(__readwrite_bug); void __pte_error(const char *file, int line, pte_t pte) { - printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); + pr_err("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); } void __pmd_error(const char *file, int line, pmd_t pmd) { - printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); + pr_err("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); } void __pgd_error(const char *file, int line, pgd_t pgd) { - printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); + pr_err("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); } asmlinkage void __div0(void) { - printk("Division by zero in kernel.\n"); + pr_err("Division by zero in kernel.\n"); dump_stack(); } EXPORT_SYMBOL(__div0); diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index cbb85c5fabf9..0bee233fef9a 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -471,7 +471,6 @@ int unwind_frame(struct stackframe *frame) void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; - register unsigned long current_sp asm ("sp"); pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); @@ -485,7 +484,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) frame.pc = regs->ARM_lr; } else if (tsk == current) { frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; + frame.sp = current_stack_pointer; frame.lr = (unsigned long)__builtin_return_address(0); frame.pc = (unsigned long)unwind_backtrace; } else { diff --git a/arch/arm/kernel/xscale-cp0.c b/arch/arm/kernel/xscale-cp0.c index e42adc6bcdb1..bdbb8853a19b 100644 --- a/arch/arm/kernel/xscale-cp0.c +++ b/arch/arm/kernel/xscale-cp0.c @@ -157,15 +157,14 @@ static int __init xscale_cp0_init(void) if (cpu_has_iwmmxt()) { #ifndef CONFIG_IWMMXT - printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " - "detected, but kernel support is missing.\n"); + pr_warn("CAUTION: XScale iWMMXt coprocessor detected, but kernel support is missing.\n"); #else - printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); + pr_info("XScale iWMMXt coprocessor detected.\n"); elf_hwcap |= HWCAP_IWMMXT; thread_register_notifier(&iwmmxt_notifier_block); #endif } else { - printk(KERN_INFO "XScale DSP coprocessor detected.\n"); + pr_info("XScale DSP coprocessor detected.\n"); thread_register_notifier(&dsp_notifier_block); cp_access |= 1; } diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 66a477a3e3cc..7a235b9952be 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -12,6 +12,7 @@ #include #include +#include /* * Prototype: @@ -77,6 +78,10 @@ stmdb sp!, {r0, r2, r3, \reg1, \reg2} .endm + .macro usave reg1 reg2 + UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) + .endm + .macro exit reg1 reg2 add sp, sp, #8 ldmfd sp!, {r0, \reg1, \reg2} diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 3bc8eb811a73..652e4d98cd47 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S @@ -53,6 +53,12 @@ * data as needed by the implementation including this code. Called * upon code entry. * + * usave reg1 reg2 + * + * Unwind annotation macro is corresponding for 'enter' macro. + * It tell unwinder that preserved some provided registers on the stack + * and additional data by a prior 'enter' macro. + * * exit reg1 reg2 * * Restore registers with the values previously saved with the @@ -67,7 +73,12 @@ */ + UNWIND( .fnstart ) enter r4, lr + UNWIND( .fnend ) + + UNWIND( .fnstart ) + usave r4, lr @ in first stmdb block subs r2, r2, #4 blt 8f @@ -79,6 +90,11 @@ 1: subs r2, r2, #(28) stmfd sp!, {r5 - r8} + UNWIND( .fnend ) + + UNWIND( .fnstart ) + usave r4, lr + UNWIND( .save {r5 - r8} ) @ in second stmfd block blt 5f CALGN( ands ip, r0, #31 ) @@ -144,7 +160,10 @@ CALGN( bcs 2b ) 7: ldmfd sp!, {r5 - r8} + UNWIND( .fnend ) @ end of second stmfd block + UNWIND( .fnstart ) + usave r4, lr @ still in first stmdb block 8: movs r2, r2, lsl #31 ldr1b r1, r3, ne, abort=21f ldr1b r1, r4, cs, abort=21f @@ -173,10 +192,13 @@ ldr1w r1, lr, abort=21f beq 17f bgt 18f + UNWIND( .fnend ) .macro forward_copy_shift pull push + UNWIND( .fnstart ) + usave r4, lr @ still in first stmdb block subs r2, r2, #28 blt 14f @@ -187,7 +209,11 @@ CALGN( bcc 15f ) 11: stmfd sp!, {r5 - r9} + UNWIND( .fnend ) + UNWIND( .fnstart ) + usave r4, lr + UNWIND( .save {r5 - r9} ) @ in new second stmfd block PLD( pld [r1, #0] ) PLD( subs r2, r2, #96 ) PLD( pld [r1, #28] ) @@ -221,7 +247,10 @@ PLD( bge 13b ) ldmfd sp!, {r5 - r9} + UNWIND( .fnend ) @ end of the second stmfd block + UNWIND( .fnstart ) + usave r4, lr @ still in first stmdb block 14: ands ip, r2, #28 beq 16f @@ -236,6 +265,7 @@ 16: sub r1, r1, #(\push / 8) b 8b + UNWIND( .fnend ) .endm diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S index d066df686e17..a9d3db16ecb5 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S @@ -12,6 +12,7 @@ #include #include +#include /* * Prototype: @@ -80,6 +81,10 @@ stmdb sp!, {r0, r2, r3, \reg1, \reg2} .endm + .macro usave reg1 reg2 + UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) + .endm + .macro exit reg1 reg2 add sp, sp, #8 ldmfd sp!, {r0, \reg1, \reg2} diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index a9b9e2287a09..7797e81e40e0 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -12,6 +12,7 @@ #include #include +#include #define LDR1W_SHIFT 0 #define STR1W_SHIFT 0 @@ -48,6 +49,10 @@ stmdb sp!, {r0, \reg1, \reg2} .endm + .macro usave reg1 reg2 + UNWIND( .save {r0, \reg1, \reg2} ) + .endm + .macro exit reg1 reg2 ldmfd sp!, {r0, \reg1, \reg2} .endm diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index d1fc0c0c342c..69a9d47fc5ab 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S @@ -12,6 +12,7 @@ #include #include +#include .text @@ -27,12 +28,17 @@ */ ENTRY(memmove) + UNWIND( .fnstart ) subs ip, r0, r1 cmphi r2, ip bls memcpy stmfd sp!, {r0, r4, lr} + UNWIND( .fnend ) + + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) @ in first stmfd block add r1, r1, r2 add r0, r0, r2 subs r2, r2, #4 @@ -45,6 +51,11 @@ ENTRY(memmove) 1: subs r2, r2, #(28) stmfd sp!, {r5 - r8} + UNWIND( .fnend ) + + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) + UNWIND( .save {r5 - r8} ) @ in second stmfd block blt 5f CALGN( ands ip, r0, #31 ) @@ -97,6 +108,10 @@ ENTRY(memmove) CALGN( bcs 2b ) 7: ldmfd sp!, {r5 - r8} + UNWIND( .fnend ) @ end of second stmfd block + + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block 8: movs r2, r2, lsl #31 ldrneb r3, [r1, #-1]! @@ -124,10 +139,13 @@ ENTRY(memmove) ldr r3, [r1, #0] beq 17f blt 18f + UNWIND( .fnend ) .macro backward_copy_shift push pull + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block subs r2, r2, #28 blt 14f @@ -137,6 +155,11 @@ ENTRY(memmove) CALGN( bcc 15f ) 11: stmfd sp!, {r5 - r9} + UNWIND( .fnend ) + + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) + UNWIND( .save {r5 - r9} ) @ in new second stmfd block PLD( pld [r1, #-4] ) PLD( subs r2, r2, #96 ) @@ -171,6 +194,10 @@ ENTRY(memmove) PLD( bge 13b ) ldmfd sp!, {r5 - r9} + UNWIND( .fnend ) @ end of the second stmfd block + + UNWIND( .fnstart ) + UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block 14: ands ip, r2, #28 beq 16f @@ -186,6 +213,7 @@ ENTRY(memmove) 16: add r1, r1, #(\pull / 8) b 8b + UNWIND( .fnend ) .endm diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 671455c854fa..a4ee97b5a2bf 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -11,11 +11,13 @@ */ #include #include +#include .text .align 5 ENTRY(memset) +UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? mov ip, r0 @ preserve r0 as return value bne 6f @ 1 @@ -34,6 +36,9 @@ ENTRY(memset) * We need 2 extra registers for this loop - use r8 and the LR */ stmfd sp!, {r8, lr} +UNWIND( .fnend ) +UNWIND( .fnstart ) +UNWIND( .save {r8, lr} ) mov r8, r1 mov lr, r1 @@ -53,6 +58,7 @@ ENTRY(memset) tst r2, #16 stmneia ip!, {r1, r3, r8, lr} ldmfd sp!, {r8, lr} +UNWIND( .fnend ) #else @@ -62,6 +68,9 @@ ENTRY(memset) */ stmfd sp!, {r4-r8, lr} +UNWIND( .fnend ) +UNWIND( .fnstart ) +UNWIND( .save {r4-r8, lr} ) mov r4, r1 mov r5, r1 mov r6, r1 @@ -94,9 +103,11 @@ ENTRY(memset) tst r2, #16 stmneia ip!, {r4-r7} ldmfd sp!, {r4-r8, lr} +UNWIND( .fnend ) #endif +UNWIND( .fnstart ) 4: tst r2, #8 stmneia ip!, {r1, r3} tst r2, #4 @@ -120,4 +131,5 @@ ENTRY(memset) strb r1, [ip], #1 @ 1 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) b 1b +UNWIND( .fnend ) ENDPROC(memset) diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S index 385ccb306fa2..0eded952e089 100644 --- a/arch/arm/lib/memzero.S +++ b/arch/arm/lib/memzero.S @@ -9,6 +9,7 @@ */ #include #include +#include .text .align 5 @@ -18,6 +19,7 @@ * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we * don't bother; we use byte stores instead. */ +UNWIND( .fnstart ) 1: subs r1, r1, #4 @ 1 do we have enough blt 5f @ 1 bytes to align with? cmp r3, #2 @ 1 @@ -47,6 +49,9 @@ ENTRY(__memzero) * use the LR */ str lr, [sp, #-4]! @ 1 +UNWIND( .fnend ) +UNWIND( .fnstart ) +UNWIND( .save {lr} ) mov ip, r2 @ 1 mov lr, r2 @ 1 @@ -66,6 +71,7 @@ ENTRY(__memzero) tst r1, #16 @ 1 16 bytes or more? stmneia r0!, {r2, r3, ip, lr} @ 4 ldr lr, [sp], #4 @ 1 +UNWIND( .fnend ) #else @@ -75,6 +81,9 @@ ENTRY(__memzero) */ stmfd sp!, {r4-r7, lr} +UNWIND( .fnend ) +UNWIND( .fnstart ) +UNWIND( .save {r4-r7, lr} ) mov r4, r2 mov r5, r2 mov r6, r2 @@ -105,9 +114,11 @@ ENTRY(__memzero) tst r1, #16 stmneia r0!, {r4-r7} ldmfd sp!, {r4-r7, lr} +UNWIND( .fnend ) #endif +UNWIND( .fnstart ) 4: tst r1, #8 @ 1 8 bytes or more? stmneia r0!, {r2, r3} @ 2 tst r1, #4 @ 1 4 bytes or more? @@ -122,4 +133,5 @@ ENTRY(__memzero) tst r1, #1 @ 1 a byte left over strneb r2, [r0], #1 @ 1 ret lr @ 1 +UNWIND( .fnend ) ENDPROC(__memzero) diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c index 9fa6a990cf03..03c75a811cb0 100644 --- a/arch/arm/mach-sa1100/clock.c +++ b/arch/arm/mach-sa1100/clock.c @@ -15,10 +15,12 @@ #include #include +#include struct clkops { void (*enable)(struct clk *); void (*disable)(struct clk *); + unsigned long (*get_rate)(struct clk *); }; struct clk { @@ -33,13 +35,6 @@ struct clk clk_##_name = { \ static DEFINE_SPINLOCK(clocks_lock); -/* Dummy clk routine to build generic kernel parts that may be using them */ -unsigned long clk_get_rate(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_get_rate); - static void clk_gpio27_enable(struct clk *clk) { /* @@ -58,6 +53,19 @@ static void clk_gpio27_disable(struct clk *clk) GAFR &= ~GPIO_32_768kHz; } +static void clk_cpu_enable(struct clk *clk) +{ +} + +static void clk_cpu_disable(struct clk *clk) +{ +} + +static unsigned long clk_cpu_get_rate(struct clk *clk) +{ + return sa11x0_getspeed(0) * 1000; +} + int clk_enable(struct clk *clk) { unsigned long flags; @@ -87,16 +95,37 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk && clk->ops && clk->ops->get_rate) + return clk->ops->get_rate(clk); + + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + const struct clkops clk_gpio27_ops = { .enable = clk_gpio27_enable, .disable = clk_gpio27_disable, }; +const struct clkops clk_cpu_ops = { + .enable = clk_cpu_enable, + .disable = clk_cpu_disable, + .get_rate = clk_cpu_get_rate, +}; + static DEFINE_CLK(gpio27, &clk_gpio27_ops); +static DEFINE_CLK(cpu, &clk_cpu_ops); + static struct clk_lookup sa11xx_clkregs[] = { CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), CLKDEV_INIT("sa1100-rtc", NULL, NULL), + CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu), + CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu), + /* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */ + CLKDEV_INIT("1800", NULL, &clk_cpu), }; static int __init sa11xx_clk_init(void) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 108939f8d053..b90c7d828391 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include