diff options
92 files changed, 1592 insertions, 850 deletions
diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index 38dc06d0a791..4178ebda6e66 100644 --- a/Documentation/arm/memory.txt +++ b/Documentation/arm/memory.txt | |||
@@ -41,7 +41,7 @@ fffe8000 fffeffff DTCM mapping area for platforms with | |||
41 | fffe0000 fffe7fff ITCM mapping area for platforms with | 41 | fffe0000 fffe7fff ITCM mapping area for platforms with |
42 | ITCM mounted inside the CPU. | 42 | ITCM mounted inside the CPU. |
43 | 43 | ||
44 | ffc00000 ffdfffff Fixmap mapping region. Addresses provided | 44 | ffc00000 ffefffff Fixmap mapping region. Addresses provided |
45 | by fix_to_virt() will be located here. | 45 | by fix_to_virt() will be located here. |
46 | 46 | ||
47 | fee00000 feffffff Mapping of PCI I/O space. This is a static | 47 | fee00000 feffffff Mapping of PCI I/O space. This is a static |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 0e5ea26b255a..44fe1d28a163 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: | |||
468 | - set the power.irq_safe flag for the device, causing the runtime-PM | 468 | - set the power.irq_safe flag for the device, causing the runtime-PM |
469 | callbacks to be invoked with interrupts off | 469 | callbacks to be invoked with interrupts off |
470 | 470 | ||
471 | bool pm_runtime_is_irq_safe(struct device *dev); | ||
472 | - return true if power.irq_safe flag was set for the device, causing | ||
473 | the runtime-PM callbacks to be invoked with interrupts off | ||
474 | |||
471 | void pm_runtime_mark_last_busy(struct device *dev); | 475 | void pm_runtime_mark_last_busy(struct device *dev); |
472 | - set the power.last_busy field to the current time | 476 | - set the power.last_busy field to the current time |
473 | 477 | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c8424a85bc04..0bee1fe209b1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -687,7 +687,9 @@ config ARCH_SA1100 | |||
687 | select CPU_SA1100 | 687 | select CPU_SA1100 |
688 | select GENERIC_CLOCKEVENTS | 688 | select GENERIC_CLOCKEVENTS |
689 | select HAVE_IDE | 689 | select HAVE_IDE |
690 | select IRQ_DOMAIN | ||
690 | select ISA | 691 | select ISA |
692 | select MULTI_IRQ_HANDLER | ||
691 | select NEED_MACH_MEMORY_H | 693 | select NEED_MACH_MEMORY_H |
692 | select SPARSE_IRQ | 694 | select SPARSE_IRQ |
693 | help | 695 | 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) | |||
282 | } | 282 | } |
283 | 283 | ||
284 | if (i == 8) | 284 | if (i == 8) |
285 | printk(KERN_ERR "Danger Will Robinson: failed to " | 285 | pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", |
286 | "re-trigger IRQ%d\n", d->irq); | 286 | d->irq); |
287 | return i == 8 ? -1 : 0; | 287 | return i == 8 ? -1 : 0; |
288 | } | 288 | } |
289 | 289 | ||
@@ -384,8 +384,8 @@ static int sa1111_retrigger_highirq(struct irq_data *d) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | if (i == 8) | 386 | if (i == 8) |
387 | printk(KERN_ERR "Danger Will Robinson: failed to " | 387 | pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", |
388 | "re-trigger IRQ%d\n", d->irq); | 388 | d->irq); |
389 | return i == 8 ? -1 : 0; | 389 | return i == 8 ? -1 : 0; |
390 | } | 390 | } |
391 | 391 | ||
@@ -740,9 +740,8 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
740 | goto err_unmap; | 740 | goto err_unmap; |
741 | } | 741 | } |
742 | 742 | ||
743 | printk(KERN_INFO "SA1111 Microprocessor Companion Chip: " | 743 | pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n", |
744 | "silicon revision %lx, metal revision %lx\n", | 744 | (id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK); |
745 | (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); | ||
746 | 745 | ||
747 | /* | 746 | /* |
748 | * We found it. Wake the chip up, and initialise. | 747 | * We found it. Wake the chip up, and initialise. |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 10e78d00a0bb..2d46862e7bef 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -487,6 +487,16 @@ int set_memory_rw(unsigned long addr, int numpages); | |||
487 | int set_memory_x(unsigned long addr, int numpages); | 487 | int set_memory_x(unsigned long addr, int numpages); |
488 | int set_memory_nx(unsigned long addr, int numpages); | 488 | int set_memory_nx(unsigned long addr, int numpages); |
489 | 489 | ||
490 | #ifdef CONFIG_DEBUG_RODATA | ||
491 | void mark_rodata_ro(void); | ||
492 | void set_kernel_text_rw(void); | ||
493 | void set_kernel_text_ro(void); | ||
494 | #else | ||
495 | static inline void set_kernel_text_rw(void) { } | ||
496 | static inline void set_kernel_text_ro(void) { } | ||
497 | #endif | ||
498 | |||
490 | void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, | 499 | void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, |
491 | void *kaddr, unsigned long len); | 500 | void *kaddr, unsigned long len); |
501 | |||
492 | #endif | 502 | #endif |
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index 74124b0d0d79..0415eae1df27 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h | |||
@@ -2,27 +2,24 @@ | |||
2 | #define _ASM_FIXMAP_H | 2 | #define _ASM_FIXMAP_H |
3 | 3 | ||
4 | #define FIXADDR_START 0xffc00000UL | 4 | #define FIXADDR_START 0xffc00000UL |
5 | #define FIXADDR_TOP 0xffe00000UL | 5 | #define FIXADDR_END 0xfff00000UL |
6 | #define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) | 6 | #define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE) |
7 | 7 | ||
8 | #define FIX_KMAP_NR_PTES (FIXADDR_SIZE >> PAGE_SHIFT) | 8 | #include <asm/kmap_types.h> |
9 | 9 | ||
10 | #define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) | 10 | enum fixed_addresses { |
11 | #define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) | 11 | FIX_KMAP_BEGIN, |
12 | FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, | ||
12 | 13 | ||
13 | extern void __this_fixmap_does_not_exist(void); | 14 | /* Support writing RO kernel text via kprobes, jump labels, etc. */ |
15 | FIX_TEXT_POKE0, | ||
16 | FIX_TEXT_POKE1, | ||
14 | 17 | ||
15 | static inline unsigned long fix_to_virt(const unsigned int idx) | 18 | __end_of_fixed_addresses |
16 | { | 19 | }; |
17 | if (idx >= FIX_KMAP_NR_PTES) | ||
18 | __this_fixmap_does_not_exist(); | ||
19 | return __fix_to_virt(idx); | ||
20 | } | ||
21 | 20 | ||
22 | static inline unsigned int virt_to_fix(const unsigned long vaddr) | 21 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); |
23 | { | 22 | |
24 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); | 23 | #include <asm-generic/fixmap.h> |
25 | return __virt_to_fix(vaddr); | ||
26 | } | ||
27 | 24 | ||
28 | #endif | 25 | #endif |
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) | |||
8 | { | 8 | { |
9 | extern unsigned long irq_err_count; | 9 | extern unsigned long irq_err_count; |
10 | irq_err_count++; | 10 | irq_err_count++; |
11 | pr_crit("unexpected IRQ trap at vector %02x\n", irq); | ||
11 | } | 12 | } |
12 | 13 | ||
13 | void set_irq_flags(unsigned int irq, unsigned int flags); | 14 | 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); | |||
219 | bool __mcpm_outbound_enter_critical(unsigned int this_cpu, unsigned int cluster); | 219 | bool __mcpm_outbound_enter_critical(unsigned int this_cpu, unsigned int cluster); |
220 | int __mcpm_cluster_state(unsigned int cluster); | 220 | int __mcpm_cluster_state(unsigned int cluster); |
221 | 221 | ||
222 | /** | ||
223 | * mcpm_sync_init - Initialize the cluster synchronization support | ||
224 | * | ||
225 | * @power_up_setup: platform specific function invoked during very | ||
226 | * early CPU/cluster bringup stage. | ||
227 | * | ||
228 | * This prepares memory used by vlocks and the MCPM state machine used | ||
229 | * across CPUs that may have their caches active or inactive. Must be | ||
230 | * called only after a successful call to mcpm_platform_register(). | ||
231 | * | ||
232 | * The power_up_setup argument is a pointer to assembly code called when | ||
233 | * the MMU and caches are still disabled during boot and no stack space is | ||
234 | * available. The affinity level passed to that code corresponds to the | ||
235 | * resource that needs to be initialized (e.g. 1 for cluster level, 0 for | ||
236 | * CPU level). Proper exclusion mechanisms are already activated at that | ||
237 | * point. | ||
238 | */ | ||
222 | int __init mcpm_sync_init( | 239 | int __init mcpm_sync_init( |
223 | void (*power_up_setup)(unsigned int affinity_level)); | 240 | void (*power_up_setup)(unsigned int affinity_level)); |
224 | 241 | ||
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) | |||
30 | static inline unsigned long __my_cpu_offset(void) | 30 | static inline unsigned long __my_cpu_offset(void) |
31 | { | 31 | { |
32 | unsigned long off; | 32 | unsigned long off; |
33 | register unsigned long *sp asm ("sp"); | ||
34 | 33 | ||
35 | /* | 34 | /* |
36 | * Read TPIDRPRW. | 35 | * Read TPIDRPRW. |
37 | * We want to allow caching the value, so avoid using volatile and | 36 | * We want to allow caching the value, so avoid using volatile and |
38 | * instead use a fake stack read to hazard against barrier(). | 37 | * instead use a fake stack read to hazard against barrier(). |
39 | */ | 38 | */ |
40 | asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp)); | 39 | asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) |
40 | : "Q" (*(const unsigned long *)current_stack_pointer)); | ||
41 | 41 | ||
42 | return off; | 42 | return off; |
43 | } | 43 | } |
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) | |||
157 | static inline void | 157 | static inline void |
158 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | 158 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) |
159 | { | 159 | { |
160 | __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); | 160 | extern pmdval_t user_pmd_table; |
161 | pmdval_t prot; | ||
162 | |||
163 | if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE)) | ||
164 | prot = user_pmd_table; | ||
165 | else | ||
166 | prot = _PAGE_USER_TABLE; | ||
167 | |||
168 | __pmd_populate(pmdp, page_to_phys(ptep), prot); | ||
161 | } | 169 | } |
162 | #define pmd_pgtable(pmd) pmd_page(pmd) | 170 | #define pmd_pgtable(pmd) pmd_page(pmd) |
163 | 171 | ||
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 @@ | |||
20 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | 20 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) |
21 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) | 21 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) |
22 | #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) | 22 | #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) |
23 | #define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ | ||
23 | #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) | 24 | #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) |
24 | #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) | 25 | #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) |
25 | #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ | 26 | #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ |
26 | /* | 27 | /* |
27 | * - section | 28 | * - section |
28 | */ | 29 | */ |
30 | #define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ | ||
29 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) | 31 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) |
30 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) | 32 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) |
31 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ | 33 | #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 @@ | |||
76 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | 76 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ |
77 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ | 77 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ |
78 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ | 78 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ |
79 | #define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */ | ||
79 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ | 80 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ |
80 | 81 | ||
81 | /* | 82 | /* |
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, | |||
252 | set_pte_ext(ptep, pteval, ext); | 252 | set_pte_ext(ptep, pteval, ext); |
253 | } | 253 | } |
254 | 254 | ||
255 | #define PTE_BIT_FUNC(fn,op) \ | 255 | static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) |
256 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 256 | { |
257 | 257 | pte_val(pte) &= ~pgprot_val(prot); | |
258 | PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY); | 258 | return pte; |
259 | PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY); | 259 | } |
260 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); | 260 | |
261 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); | 261 | static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot) |
262 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); | 262 | { |
263 | PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); | 263 | pte_val(pte) |= pgprot_val(prot); |
264 | PTE_BIT_FUNC(mkexec, &= ~L_PTE_XN); | 264 | return pte; |
265 | PTE_BIT_FUNC(mknexec, |= L_PTE_XN); | 265 | } |
266 | |||
267 | static inline pte_t pte_wrprotect(pte_t pte) | ||
268 | { | ||
269 | return set_pte_bit(pte, __pgprot(L_PTE_RDONLY)); | ||
270 | } | ||
271 | |||
272 | static inline pte_t pte_mkwrite(pte_t pte) | ||
273 | { | ||
274 | return clear_pte_bit(pte, __pgprot(L_PTE_RDONLY)); | ||
275 | } | ||
276 | |||
277 | static inline pte_t pte_mkclean(pte_t pte) | ||
278 | { | ||
279 | return clear_pte_bit(pte, __pgprot(L_PTE_DIRTY)); | ||
280 | } | ||
281 | |||
282 | static inline pte_t pte_mkdirty(pte_t pte) | ||
283 | { | ||
284 | return set_pte_bit(pte, __pgprot(L_PTE_DIRTY)); | ||
285 | } | ||
286 | |||
287 | static inline pte_t pte_mkold(pte_t pte) | ||
288 | { | ||
289 | return clear_pte_bit(pte, __pgprot(L_PTE_YOUNG)); | ||
290 | } | ||
291 | |||
292 | static inline pte_t pte_mkyoung(pte_t pte) | ||
293 | { | ||
294 | return set_pte_bit(pte, __pgprot(L_PTE_YOUNG)); | ||
295 | } | ||
296 | |||
297 | static inline pte_t pte_mkexec(pte_t pte) | ||
298 | { | ||
299 | return clear_pte_bit(pte, __pgprot(L_PTE_XN)); | ||
300 | } | ||
301 | |||
302 | static inline pte_t pte_mknexec(pte_t pte) | ||
303 | { | ||
304 | return set_pte_bit(pte, __pgprot(L_PTE_XN)); | ||
305 | } | ||
266 | 306 | ||
267 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 307 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
268 | { | 308 | { |
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) | |||
154 | return regs->ARM_sp; | 154 | return regs->ARM_sp; |
155 | } | 155 | } |
156 | 156 | ||
157 | #define current_pt_regs(void) ({ \ | 157 | #define current_pt_regs(void) ({ (struct pt_regs *) \ |
158 | register unsigned long sp asm ("sp"); \ | 158 | ((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \ |
159 | (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \ | ||
160 | }) | 159 | }) |
161 | 160 | ||
162 | #endif /* __ASSEMBLY__ */ | 161 | #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 | |||
@@ -90,14 +90,19 @@ struct thread_info { | |||
90 | #define init_stack (init_thread_union.stack) | 90 | #define init_stack (init_thread_union.stack) |
91 | 91 | ||
92 | /* | 92 | /* |
93 | * how to get the current stack pointer in C | ||
94 | */ | ||
95 | register unsigned long current_stack_pointer asm ("sp"); | ||
96 | |||
97 | /* | ||
93 | * how to get the thread information struct from C | 98 | * how to get the thread information struct from C |
94 | */ | 99 | */ |
95 | static inline struct thread_info *current_thread_info(void) __attribute_const__; | 100 | static inline struct thread_info *current_thread_info(void) __attribute_const__; |
96 | 101 | ||
97 | static inline struct thread_info *current_thread_info(void) | 102 | static inline struct thread_info *current_thread_info(void) |
98 | { | 103 | { |
99 | register unsigned long sp asm ("sp"); | 104 | return (struct thread_info *) |
100 | return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); | 105 | (current_stack_pointer & ~(THREAD_SIZE - 1)); |
101 | } | 106 | } |
102 | 107 | ||
103 | #define thread_saved_pc(tsk) \ | 108 | #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 @@ | |||
22 | #define FPSID_NODOUBLE (1<<20) | 22 | #define FPSID_NODOUBLE (1<<20) |
23 | #define FPSID_ARCH_BIT (16) | 23 | #define FPSID_ARCH_BIT (16) |
24 | #define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) | 24 | #define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) |
25 | #define FPSID_CPUID_ARCH_MASK (0x7F << FPSID_ARCH_BIT) | ||
25 | #define FPSID_PART_BIT (8) | 26 | #define FPSID_PART_BIT (8) |
26 | #define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) | 27 | #define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) |
27 | #define FPSID_VARIANT_BIT (4) | 28 | #define FPSID_VARIANT_BIT (4) |
@@ -75,6 +76,10 @@ | |||
75 | /* MVFR0 bits */ | 76 | /* MVFR0 bits */ |
76 | #define MVFR0_A_SIMD_BIT (0) | 77 | #define MVFR0_A_SIMD_BIT (0) |
77 | #define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) | 78 | #define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) |
79 | #define MVFR0_SP_BIT (4) | ||
80 | #define MVFR0_SP_MASK (0xf << MVFR0_SP_BIT) | ||
81 | #define MVFR0_DP_BIT (8) | ||
82 | #define MVFR0_DP_MASK (0xf << MVFR0_DP_BIT) | ||
78 | 83 | ||
79 | /* Bit patterns for decoding the packaged operation descriptors */ | 84 | /* Bit patterns for decoding the packaged operation descriptors */ |
80 | #define VFPOPDESC_LENGTH_BIT (9) | 85 | #define VFPOPDESC_LENGTH_BIT (9) |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 8dcbed5016ac..f290ac892a95 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -47,6 +47,7 @@ endif | |||
47 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 47 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
48 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | 48 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
49 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o | 49 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o |
50 | obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o | ||
50 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | 51 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o |
51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 52 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 53 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
@@ -67,7 +68,7 @@ test-kprobes-objs += kprobes-test-arm.o | |||
67 | endif | 68 | endif |
68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 69 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 70 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
70 | obj-$(CONFIG_KGDB) += kgdb.o | 71 | obj-$(CONFIG_KGDB) += kgdb.o patch.o |
71 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 72 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
72 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 73 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
73 | obj-$(CONFIG_OF) += devtree.o | 74 | obj-$(CONFIG_OF) += devtree.o |
@@ -84,6 +85,7 @@ obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o | |||
84 | obj-$(CONFIG_IWMMXT) += iwmmxt.o | 85 | obj-$(CONFIG_IWMMXT) += iwmmxt.o |
85 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o | 86 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o |
86 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o | 87 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o |
88 | CFLAGS_pj4-cp0.o := -marm | ||
87 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 89 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
88 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o | 90 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o |
89 | 91 | ||
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) | |||
97 | struct tag *tag = taglist; | 97 | struct tag *tag = taglist; |
98 | 98 | ||
99 | if (params->u1.s.page_size != PAGE_SIZE) { | 99 | if (params->u1.s.page_size != PAGE_SIZE) { |
100 | printk(KERN_WARNING "Warning: bad configuration page, " | 100 | pr_warn("Warning: bad configuration page, trying to continue\n"); |
101 | "trying to continue\n"); | ||
102 | return; | 101 | return; |
103 | } | 102 | } |
104 | 103 | ||
@@ -109,8 +108,7 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) | |||
109 | params->u1.s.nr_pages != 0x04000 && | 108 | params->u1.s.nr_pages != 0x04000 && |
110 | params->u1.s.nr_pages != 0x08000 && | 109 | params->u1.s.nr_pages != 0x08000 && |
111 | params->u1.s.nr_pages != 0x10000) { | 110 | params->u1.s.nr_pages != 0x10000) { |
112 | printk(KERN_WARNING "Warning: bad NeTTrom parameters " | 111 | pr_warn("Warning: bad NeTTrom parameters detected, using defaults\n"); |
113 | "detected, using defaults\n"); | ||
114 | 112 | ||
115 | params->u1.s.nr_pages = 0x1000; /* 16MB */ | 113 | params->u1.s.nr_pages = 0x1000; /* 16MB */ |
116 | params->u1.s.ramdisk_size = 0; | 114 | 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) | |||
167 | { | 167 | { |
168 | for (; t->hdr.size; t = tag_next(t)) | 168 | for (; t->hdr.size; t = tag_next(t)) |
169 | if (!parse_tag(t)) | 169 | if (!parse_tag(t)) |
170 | printk(KERN_WARNING | 170 | pr_warn("Ignoring unrecognised tag 0x%08x\n", |
171 | "Ignoring unrecognised tag 0x%08x\n", | ||
172 | t->hdr.tag); | 171 | t->hdr.tag); |
173 | } | 172 | } |
174 | 173 | ||
@@ -193,7 +192,7 @@ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) | |||
193 | */ | 192 | */ |
194 | for_each_machine_desc(p) | 193 | for_each_machine_desc(p) |
195 | if (machine_nr == p->nr) { | 194 | if (machine_nr == p->nr) { |
196 | printk("Machine: %s\n", p->name); | 195 | pr_info("Machine: %s\n", p->name); |
197 | mdesc = p; | 196 | mdesc = p; |
198 | break; | 197 | break; |
199 | } | 198 | } |
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) | |||
41 | size_t size; | 41 | size_t size; |
42 | 42 | ||
43 | if (tag->hdr.tag != ATAG_CORE) { | 43 | if (tag->hdr.tag != ATAG_CORE) { |
44 | printk(KERN_INFO "No ATAGs?"); | 44 | pr_info("No ATAGs?"); |
45 | return -EINVAL; | 45 | return -EINVAL; |
46 | } | 46 | } |
47 | 47 | ||
@@ -68,7 +68,7 @@ static int __init init_atags_procfs(void) | |||
68 | 68 | ||
69 | nomem: | 69 | nomem: |
70 | kfree(b); | 70 | kfree(b); |
71 | printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); | 71 | pr_err("Exporting ATAGs: not enough memory\n"); |
72 | 72 | ||
73 | return -ENOMEM; | 73 | return -ENOMEM; |
74 | } | 74 | } |
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index daaff73bc776..a4effd6d8f2f 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
@@ -364,7 +364,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) | |||
364 | /* | 364 | /* |
365 | * Report what we did for this bus | 365 | * Report what we did for this bus |
366 | */ | 366 | */ |
367 | printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", | 367 | pr_info("PCI: bus%d: Fast back to back transfers %sabled\n", |
368 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); | 368 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); |
369 | } | 369 | } |
370 | EXPORT_SYMBOL(pcibios_fixup_bus); | 370 | 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) | |||
213 | for (chan = 0; chan < 8; chan++) { | 213 | for (chan = 0; chan < 8; chan++) { |
214 | int ret = isa_dma_add(chan, &isa_dma[chan]); | 214 | int ret = isa_dma_add(chan, &isa_dma[chan]); |
215 | if (ret) | 215 | if (ret) |
216 | printk(KERN_ERR "ISADMA%u: unable to register: %d\n", | 216 | pr_err("ISADMA%u: unable to register: %d\n", |
217 | chan, ret); | 217 | chan, ret); |
218 | } | 218 | } |
219 | 219 | ||
220 | request_dma(DMA_ISA_CASCADE, "cascade"); | 220 | 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) | |||
79 | return ret; | 79 | return ret; |
80 | 80 | ||
81 | bad_dma: | 81 | bad_dma: |
82 | printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan); | 82 | pr_err("dma: trying to allocate DMA%d\n", chan); |
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | 84 | ||
85 | busy: | 85 | busy: |
@@ -100,7 +100,7 @@ void free_dma(unsigned int chan) | |||
100 | goto bad_dma; | 100 | goto bad_dma; |
101 | 101 | ||
102 | if (dma->active) { | 102 | if (dma->active) { |
103 | printk(KERN_ERR "dma%d: freeing active DMA\n", chan); | 103 | pr_err("dma%d: freeing active DMA\n", chan); |
104 | dma->d_ops->disable(chan, dma); | 104 | dma->d_ops->disable(chan, dma); |
105 | dma->active = 0; | 105 | dma->active = 0; |
106 | } | 106 | } |
@@ -111,11 +111,11 @@ void free_dma(unsigned int chan) | |||
111 | return; | 111 | return; |
112 | } | 112 | } |
113 | 113 | ||
114 | printk(KERN_ERR "dma%d: trying to free free DMA\n", chan); | 114 | pr_err("dma%d: trying to free free DMA\n", chan); |
115 | return; | 115 | return; |
116 | 116 | ||
117 | bad_dma: | 117 | bad_dma: |
118 | printk(KERN_ERR "dma: trying to free DMA%d\n", chan); | 118 | pr_err("dma: trying to free DMA%d\n", chan); |
119 | } | 119 | } |
120 | EXPORT_SYMBOL(free_dma); | 120 | EXPORT_SYMBOL(free_dma); |
121 | 121 | ||
@@ -126,8 +126,7 @@ void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) | |||
126 | dma_t *dma = dma_channel(chan); | 126 | dma_t *dma = dma_channel(chan); |
127 | 127 | ||
128 | if (dma->active) | 128 | if (dma->active) |
129 | printk(KERN_ERR "dma%d: altering DMA SG while " | 129 | pr_err("dma%d: altering DMA SG while DMA active\n", chan); |
130 | "DMA active\n", chan); | ||
131 | 130 | ||
132 | dma->sg = sg; | 131 | dma->sg = sg; |
133 | dma->sgcount = nr_sg; | 132 | dma->sgcount = nr_sg; |
@@ -144,8 +143,7 @@ void __set_dma_addr (unsigned int chan, void *addr) | |||
144 | dma_t *dma = dma_channel(chan); | 143 | dma_t *dma = dma_channel(chan); |
145 | 144 | ||
146 | if (dma->active) | 145 | if (dma->active) |
147 | printk(KERN_ERR "dma%d: altering DMA address while " | 146 | pr_err("dma%d: altering DMA address while DMA active\n", chan); |
148 | "DMA active\n", chan); | ||
149 | 147 | ||
150 | dma->sg = NULL; | 148 | dma->sg = NULL; |
151 | dma->addr = addr; | 149 | dma->addr = addr; |
@@ -162,8 +160,7 @@ void set_dma_count (unsigned int chan, unsigned long count) | |||
162 | dma_t *dma = dma_channel(chan); | 160 | dma_t *dma = dma_channel(chan); |
163 | 161 | ||
164 | if (dma->active) | 162 | if (dma->active) |
165 | printk(KERN_ERR "dma%d: altering DMA count while " | 163 | pr_err("dma%d: altering DMA count while DMA active\n", chan); |
166 | "DMA active\n", chan); | ||
167 | 164 | ||
168 | dma->sg = NULL; | 165 | dma->sg = NULL; |
169 | dma->count = count; | 166 | dma->count = count; |
@@ -178,8 +175,7 @@ void set_dma_mode (unsigned int chan, unsigned int mode) | |||
178 | dma_t *dma = dma_channel(chan); | 175 | dma_t *dma = dma_channel(chan); |
179 | 176 | ||
180 | if (dma->active) | 177 | if (dma->active) |
181 | printk(KERN_ERR "dma%d: altering DMA mode while " | 178 | pr_err("dma%d: altering DMA mode while DMA active\n", chan); |
182 | "DMA active\n", chan); | ||
183 | 179 | ||
184 | dma->dma_mode = mode; | 180 | dma->dma_mode = mode; |
185 | dma->invalid = 1; | 181 | dma->invalid = 1; |
@@ -202,7 +198,7 @@ void enable_dma (unsigned int chan) | |||
202 | return; | 198 | return; |
203 | 199 | ||
204 | free_dma: | 200 | free_dma: |
205 | printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan); | 201 | pr_err("dma%d: trying to enable free DMA\n", chan); |
206 | BUG(); | 202 | BUG(); |
207 | } | 203 | } |
208 | EXPORT_SYMBOL(enable_dma); | 204 | EXPORT_SYMBOL(enable_dma); |
@@ -223,7 +219,7 @@ void disable_dma (unsigned int chan) | |||
223 | return; | 219 | return; |
224 | 220 | ||
225 | free_dma: | 221 | free_dma: |
226 | printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan); | 222 | pr_err("dma%d: trying to disable free DMA\n", chan); |
227 | BUG(); | 223 | BUG(); |
228 | } | 224 | } |
229 | EXPORT_SYMBOL(disable_dma); | 225 | EXPORT_SYMBOL(disable_dma); |
@@ -240,7 +236,7 @@ EXPORT_SYMBOL(dma_channel_active); | |||
240 | 236 | ||
241 | void set_dma_page(unsigned int chan, char pagenr) | 237 | void set_dma_page(unsigned int chan, char pagenr) |
242 | { | 238 | { |
243 | printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan); | 239 | pr_err("dma%d: trying to set_dma_page\n", chan); |
244 | } | 240 | } |
245 | EXPORT_SYMBOL(set_dma_page); | 241 | EXPORT_SYMBOL(set_dma_page); |
246 | 242 | ||
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) | |||
109 | #undef CALL | 109 | #undef CALL |
110 | #define CALL(x) .long x | 110 | #define CALL(x) .long x |
111 | 111 | ||
112 | #ifdef CONFIG_FUNCTION_TRACER | ||
113 | /* | ||
114 | * When compiling with -pg, gcc inserts a call to the mcount routine at the | ||
115 | * start of every function. In mcount, apart from the function's address (in | ||
116 | * lr), we need to get hold of the function's caller's address. | ||
117 | * | ||
118 | * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | ||
119 | * | ||
120 | * bl mcount | ||
121 | * | ||
122 | * These versions have the limitation that in order for the mcount routine to | ||
123 | * be able to determine the function's caller's address, an APCS-style frame | ||
124 | * pointer (which is set up with something like the code below) is required. | ||
125 | * | ||
126 | * mov ip, sp | ||
127 | * push {fp, ip, lr, pc} | ||
128 | * sub fp, ip, #4 | ||
129 | * | ||
130 | * With EABI, these frame pointers are not available unless -mapcs-frame is | ||
131 | * specified, and if building as Thumb-2, not even then. | ||
132 | * | ||
133 | * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | ||
134 | * with call sites like: | ||
135 | * | ||
136 | * push {lr} | ||
137 | * bl __gnu_mcount_nc | ||
138 | * | ||
139 | * With these compilers, frame pointers are not necessary. | ||
140 | * | ||
141 | * mcount can be thought of as a function called in the middle of a subroutine | ||
142 | * call. As such, it needs to be transparent for both the caller and the | ||
143 | * callee: the original lr needs to be restored when leaving mcount, and no | ||
144 | * registers should be clobbered. (In the __gnu_mcount_nc implementation, we | ||
145 | * clobber the ip register. This is OK because the ARM calling convention | ||
146 | * allows it to be clobbered in subroutines and doesn't use it to hold | ||
147 | * parameters.) | ||
148 | * | ||
149 | * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | ||
150 | * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | ||
151 | * arch/arm/kernel/ftrace.c). | ||
152 | */ | ||
153 | |||
154 | #ifndef CONFIG_OLD_MCOUNT | ||
155 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | ||
156 | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | ||
157 | #endif | ||
158 | #endif | ||
159 | |||
160 | .macro mcount_adjust_addr rd, rn | ||
161 | bic \rd, \rn, #1 @ clear the Thumb bit if present | ||
162 | sub \rd, \rd, #MCOUNT_INSN_SIZE | ||
163 | .endm | ||
164 | |||
165 | .macro __mcount suffix | ||
166 | mcount_enter | ||
167 | ldr r0, =ftrace_trace_function | ||
168 | ldr r2, [r0] | ||
169 | adr r0, .Lftrace_stub | ||
170 | cmp r0, r2 | ||
171 | bne 1f | ||
172 | |||
173 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
174 | ldr r1, =ftrace_graph_return | ||
175 | ldr r2, [r1] | ||
176 | cmp r0, r2 | ||
177 | bne ftrace_graph_caller\suffix | ||
178 | |||
179 | ldr r1, =ftrace_graph_entry | ||
180 | ldr r2, [r1] | ||
181 | ldr r0, =ftrace_graph_entry_stub | ||
182 | cmp r0, r2 | ||
183 | bne ftrace_graph_caller\suffix | ||
184 | #endif | ||
185 | |||
186 | mcount_exit | ||
187 | |||
188 | 1: mcount_get_lr r1 @ lr of instrumented func | ||
189 | mcount_adjust_addr r0, lr @ instrumented function | ||
190 | adr lr, BSYM(2f) | ||
191 | mov pc, r2 | ||
192 | 2: mcount_exit | ||
193 | .endm | ||
194 | |||
195 | .macro __ftrace_caller suffix | ||
196 | mcount_enter | ||
197 | |||
198 | mcount_get_lr r1 @ lr of instrumented func | ||
199 | mcount_adjust_addr r0, lr @ instrumented function | ||
200 | |||
201 | .globl ftrace_call\suffix | ||
202 | ftrace_call\suffix: | ||
203 | bl ftrace_stub | ||
204 | |||
205 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
206 | .globl ftrace_graph_call\suffix | ||
207 | ftrace_graph_call\suffix: | ||
208 | mov r0, r0 | ||
209 | #endif | ||
210 | |||
211 | mcount_exit | ||
212 | .endm | ||
213 | |||
214 | .macro __ftrace_graph_caller | ||
215 | sub r0, fp, #4 @ &lr of instrumented routine (&parent) | ||
216 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
217 | @ called from __ftrace_caller, saved in mcount_enter | ||
218 | ldr r1, [sp, #16] @ instrumented routine (func) | ||
219 | mcount_adjust_addr r1, r1 | ||
220 | #else | ||
221 | @ called from __mcount, untouched in lr | ||
222 | mcount_adjust_addr r1, lr @ instrumented routine (func) | ||
223 | #endif | ||
224 | mov r2, fp @ frame pointer | ||
225 | bl prepare_ftrace_return | ||
226 | mcount_exit | ||
227 | .endm | ||
228 | |||
229 | #ifdef CONFIG_OLD_MCOUNT | ||
230 | /* | ||
231 | * mcount | ||
232 | */ | ||
233 | |||
234 | .macro mcount_enter | ||
235 | stmdb sp!, {r0-r3, lr} | ||
236 | .endm | ||
237 | |||
238 | .macro mcount_get_lr reg | ||
239 | ldr \reg, [fp, #-4] | ||
240 | .endm | ||
241 | |||
242 | .macro mcount_exit | ||
243 | ldr lr, [fp, #-4] | ||
244 | ldmia sp!, {r0-r3, pc} | ||
245 | .endm | ||
246 | |||
247 | ENTRY(mcount) | ||
248 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
249 | stmdb sp!, {lr} | ||
250 | ldr lr, [fp, #-4] | ||
251 | ldmia sp!, {pc} | ||
252 | #else | ||
253 | __mcount _old | ||
254 | #endif | ||
255 | ENDPROC(mcount) | ||
256 | |||
257 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
258 | ENTRY(ftrace_caller_old) | ||
259 | __ftrace_caller _old | ||
260 | ENDPROC(ftrace_caller_old) | ||
261 | #endif | ||
262 | |||
263 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
264 | ENTRY(ftrace_graph_caller_old) | ||
265 | __ftrace_graph_caller | ||
266 | ENDPROC(ftrace_graph_caller_old) | ||
267 | #endif | ||
268 | |||
269 | .purgem mcount_enter | ||
270 | .purgem mcount_get_lr | ||
271 | .purgem mcount_exit | ||
272 | #endif | ||
273 | |||
274 | /* | ||
275 | * __gnu_mcount_nc | ||
276 | */ | ||
277 | |||
278 | .macro mcount_enter | ||
279 | /* | ||
280 | * This pad compensates for the push {lr} at the call site. Note that we are | ||
281 | * unable to unwind through a function which does not otherwise save its lr. | ||
282 | */ | ||
283 | UNWIND(.pad #4) | ||
284 | stmdb sp!, {r0-r3, lr} | ||
285 | UNWIND(.save {r0-r3, lr}) | ||
286 | .endm | ||
287 | |||
288 | .macro mcount_get_lr reg | ||
289 | ldr \reg, [sp, #20] | ||
290 | .endm | ||
291 | |||
292 | .macro mcount_exit | ||
293 | ldmia sp!, {r0-r3, ip, lr} | ||
294 | ret ip | ||
295 | .endm | ||
296 | |||
297 | ENTRY(__gnu_mcount_nc) | ||
298 | UNWIND(.fnstart) | ||
299 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
300 | mov ip, lr | ||
301 | ldmia sp!, {lr} | ||
302 | ret ip | ||
303 | #else | ||
304 | __mcount | ||
305 | #endif | ||
306 | UNWIND(.fnend) | ||
307 | ENDPROC(__gnu_mcount_nc) | ||
308 | |||
309 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
310 | ENTRY(ftrace_caller) | ||
311 | UNWIND(.fnstart) | ||
312 | __ftrace_caller | ||
313 | UNWIND(.fnend) | ||
314 | ENDPROC(ftrace_caller) | ||
315 | #endif | ||
316 | |||
317 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
318 | ENTRY(ftrace_graph_caller) | ||
319 | UNWIND(.fnstart) | ||
320 | __ftrace_graph_caller | ||
321 | UNWIND(.fnend) | ||
322 | ENDPROC(ftrace_graph_caller) | ||
323 | #endif | ||
324 | |||
325 | .purgem mcount_enter | ||
326 | .purgem mcount_get_lr | ||
327 | .purgem mcount_exit | ||
328 | |||
329 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
330 | .globl return_to_handler | ||
331 | return_to_handler: | ||
332 | stmdb sp!, {r0-r3} | ||
333 | mov r0, fp @ frame pointer | ||
334 | bl ftrace_return_to_handler | ||
335 | mov lr, r0 @ r0 has real ret addr | ||
336 | ldmia sp!, {r0-r3} | ||
337 | ret lr | ||
338 | #endif | ||
339 | |||
340 | ENTRY(ftrace_stub) | ||
341 | .Lftrace_stub: | ||
342 | ret lr | ||
343 | ENDPROC(ftrace_stub) | ||
344 | |||
345 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
346 | |||
347 | /*============================================================================= | 112 | /*============================================================================= |
348 | * SWI handler | 113 | * SWI handler |
349 | *----------------------------------------------------------------------------- | 114 | *----------------------------------------------------------------------------- |
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 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * published by the Free Software Foundation. | ||
5 | */ | ||
6 | |||
7 | #include <asm/assembler.h> | ||
8 | #include <asm/ftrace.h> | ||
9 | #include <asm/unwind.h> | ||
10 | |||
11 | #include "entry-header.S" | ||
12 | |||
13 | /* | ||
14 | * When compiling with -pg, gcc inserts a call to the mcount routine at the | ||
15 | * start of every function. In mcount, apart from the function's address (in | ||
16 | * lr), we need to get hold of the function's caller's address. | ||
17 | * | ||
18 | * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | ||
19 | * | ||
20 | * bl mcount | ||
21 | * | ||
22 | * These versions have the limitation that in order for the mcount routine to | ||
23 | * be able to determine the function's caller's address, an APCS-style frame | ||
24 | * pointer (which is set up with something like the code below) is required. | ||
25 | * | ||
26 | * mov ip, sp | ||
27 | * push {fp, ip, lr, pc} | ||
28 | * sub fp, ip, #4 | ||
29 | * | ||
30 | * With EABI, these frame pointers are not available unless -mapcs-frame is | ||
31 | * specified, and if building as Thumb-2, not even then. | ||
32 | * | ||
33 | * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | ||
34 | * with call sites like: | ||
35 | * | ||
36 | * push {lr} | ||
37 | * bl __gnu_mcount_nc | ||
38 | * | ||
39 | * With these compilers, frame pointers are not necessary. | ||
40 | * | ||
41 | * mcount can be thought of as a function called in the middle of a subroutine | ||
42 | * call. As such, it needs to be transparent for both the caller and the | ||
43 | * callee: the original lr needs to be restored when leaving mcount, and no | ||
44 | * registers should be clobbered. (In the __gnu_mcount_nc implementation, we | ||
45 | * clobber the ip register. This is OK because the ARM calling convention | ||
46 | * allows it to be clobbered in subroutines and doesn't use it to hold | ||
47 | * parameters.) | ||
48 | * | ||
49 | * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | ||
50 | * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | ||
51 | * arch/arm/kernel/ftrace.c). | ||
52 | */ | ||
53 | |||
54 | #ifndef CONFIG_OLD_MCOUNT | ||
55 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | ||
56 | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | ||
57 | #endif | ||
58 | #endif | ||
59 | |||
60 | .macro mcount_adjust_addr rd, rn | ||
61 | bic \rd, \rn, #1 @ clear the Thumb bit if present | ||
62 | sub \rd, \rd, #MCOUNT_INSN_SIZE | ||
63 | .endm | ||
64 | |||
65 | .macro __mcount suffix | ||
66 | mcount_enter | ||
67 | ldr r0, =ftrace_trace_function | ||
68 | ldr r2, [r0] | ||
69 | adr r0, .Lftrace_stub | ||
70 | cmp r0, r2 | ||
71 | bne 1f | ||
72 | |||
73 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
74 | ldr r1, =ftrace_graph_return | ||
75 | ldr r2, [r1] | ||
76 | cmp r0, r2 | ||
77 | bne ftrace_graph_caller\suffix | ||
78 | |||
79 | ldr r1, =ftrace_graph_entry | ||
80 | ldr r2, [r1] | ||
81 | ldr r0, =ftrace_graph_entry_stub | ||
82 | cmp r0, r2 | ||
83 | bne ftrace_graph_caller\suffix | ||
84 | #endif | ||
85 | |||
86 | mcount_exit | ||
87 | |||
88 | 1: mcount_get_lr r1 @ lr of instrumented func | ||
89 | mcount_adjust_addr r0, lr @ instrumented function | ||
90 | adr lr, BSYM(2f) | ||
91 | mov pc, r2 | ||
92 | 2: mcount_exit | ||
93 | .endm | ||
94 | |||
95 | .macro __ftrace_caller suffix | ||
96 | mcount_enter | ||
97 | |||
98 | mcount_get_lr r1 @ lr of instrumented func | ||
99 | mcount_adjust_addr r0, lr @ instrumented function | ||
100 | |||
101 | .globl ftrace_call\suffix | ||
102 | ftrace_call\suffix: | ||
103 | bl ftrace_stub | ||
104 | |||
105 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
106 | .globl ftrace_graph_call\suffix | ||
107 | ftrace_graph_call\suffix: | ||
108 | mov r0, r0 | ||
109 | #endif | ||
110 | |||
111 | mcount_exit | ||
112 | .endm | ||
113 | |||
114 | .macro __ftrace_graph_caller | ||
115 | sub r0, fp, #4 @ &lr of instrumented routine (&parent) | ||
116 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
117 | @ called from __ftrace_caller, saved in mcount_enter | ||
118 | ldr r1, [sp, #16] @ instrumented routine (func) | ||
119 | mcount_adjust_addr r1, r1 | ||
120 | #else | ||
121 | @ called from __mcount, untouched in lr | ||
122 | mcount_adjust_addr r1, lr @ instrumented routine (func) | ||
123 | #endif | ||
124 | mov r2, fp @ frame pointer | ||
125 | bl prepare_ftrace_return | ||
126 | mcount_exit | ||
127 | .endm | ||
128 | |||
129 | #ifdef CONFIG_OLD_MCOUNT | ||
130 | /* | ||
131 | * mcount | ||
132 | */ | ||
133 | |||
134 | .macro mcount_enter | ||
135 | stmdb sp!, {r0-r3, lr} | ||
136 | .endm | ||
137 | |||
138 | .macro mcount_get_lr reg | ||
139 | ldr \reg, [fp, #-4] | ||
140 | .endm | ||
141 | |||
142 | .macro mcount_exit | ||
143 | ldr lr, [fp, #-4] | ||
144 | ldmia sp!, {r0-r3, pc} | ||
145 | .endm | ||
146 | |||
147 | ENTRY(mcount) | ||
148 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
149 | stmdb sp!, {lr} | ||
150 | ldr lr, [fp, #-4] | ||
151 | ldmia sp!, {pc} | ||
152 | #else | ||
153 | __mcount _old | ||
154 | #endif | ||
155 | ENDPROC(mcount) | ||
156 | |||
157 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
158 | ENTRY(ftrace_caller_old) | ||
159 | __ftrace_caller _old | ||
160 | ENDPROC(ftrace_caller_old) | ||
161 | #endif | ||
162 | |||
163 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
164 | ENTRY(ftrace_graph_caller_old) | ||
165 | __ftrace_graph_caller | ||
166 | ENDPROC(ftrace_graph_caller_old) | ||
167 | #endif | ||
168 | |||
169 | .purgem mcount_enter | ||
170 | .purgem mcount_get_lr | ||
171 | .purgem mcount_exit | ||
172 | #endif | ||
173 | |||
174 | /* | ||
175 | * __gnu_mcount_nc | ||
176 | */ | ||
177 | |||
178 | .macro mcount_enter | ||
179 | /* | ||
180 | * This pad compensates for the push {lr} at the call site. Note that we are | ||
181 | * unable to unwind through a function which does not otherwise save its lr. | ||
182 | */ | ||
183 | UNWIND(.pad #4) | ||
184 | stmdb sp!, {r0-r3, lr} | ||
185 | UNWIND(.save {r0-r3, lr}) | ||
186 | .endm | ||
187 | |||
188 | .macro mcount_get_lr reg | ||
189 | ldr \reg, [sp, #20] | ||
190 | .endm | ||
191 | |||
192 | .macro mcount_exit | ||
193 | ldmia sp!, {r0-r3, ip, lr} | ||
194 | ret ip | ||
195 | .endm | ||
196 | |||
197 | ENTRY(__gnu_mcount_nc) | ||
198 | UNWIND(.fnstart) | ||
199 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
200 | mov ip, lr | ||
201 | ldmia sp!, {lr} | ||
202 | ret ip | ||
203 | #else | ||
204 | __mcount | ||
205 | #endif | ||
206 | UNWIND(.fnend) | ||
207 | ENDPROC(__gnu_mcount_nc) | ||
208 | |||
209 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
210 | ENTRY(ftrace_caller) | ||
211 | UNWIND(.fnstart) | ||
212 | __ftrace_caller | ||
213 | UNWIND(.fnend) | ||
214 | ENDPROC(ftrace_caller) | ||
215 | #endif | ||
216 | |||
217 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
218 | ENTRY(ftrace_graph_caller) | ||
219 | UNWIND(.fnstart) | ||
220 | __ftrace_graph_caller | ||
221 | UNWIND(.fnend) | ||
222 | ENDPROC(ftrace_graph_caller) | ||
223 | #endif | ||
224 | |||
225 | .purgem mcount_enter | ||
226 | .purgem mcount_get_lr | ||
227 | .purgem mcount_exit | ||
228 | |||
229 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
230 | .globl return_to_handler | ||
231 | return_to_handler: | ||
232 | stmdb sp!, {r0-r3} | ||
233 | mov r0, fp @ frame pointer | ||
234 | bl ftrace_return_to_handler | ||
235 | mov lr, r0 @ r0 has real ret addr | ||
236 | ldmia sp!, {r0-r3} | ||
237 | ret lr | ||
238 | #endif | ||
239 | |||
240 | ENTRY(ftrace_stub) | ||
241 | .Lftrace_stub: | ||
242 | ret lr | ||
243 | 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) | |||
213 | int length; | 213 | int length; |
214 | 214 | ||
215 | if (!t->etb_regs) { | 215 | if (!t->etb_regs) { |
216 | printk(KERN_INFO "No tracing hardware found\n"); | 216 | pr_info("No tracing hardware found\n"); |
217 | return; | 217 | return; |
218 | } | 218 | } |
219 | 219 | ||
@@ -229,11 +229,11 @@ static void etm_dump(void) | |||
229 | 229 | ||
230 | etb_writel(t, first, ETBR_READADDR); | 230 | etb_writel(t, first, ETBR_READADDR); |
231 | 231 | ||
232 | printk(KERN_INFO "Trace buffer contents length: %d\n", length); | 232 | pr_info("Trace buffer contents length: %d\n", length); |
233 | printk(KERN_INFO "--- ETB buffer begin ---\n"); | 233 | pr_info("--- ETB buffer begin ---\n"); |
234 | for (; length; length--) | 234 | for (; length; length--) |
235 | printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); | 235 | printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); |
236 | printk(KERN_INFO "\n--- ETB buffer end ---\n"); | 236 | pr_info("\n--- ETB buffer end ---\n"); |
237 | 237 | ||
238 | /* deassert the overflow bit */ | 238 | /* deassert the overflow bit */ |
239 | etb_writel(t, 1, ETBR_CTRL); | 239 | etb_writel(t, 1, ETBR_CTRL); |
@@ -633,14 +633,14 @@ static int __init etm_init(void) | |||
633 | 633 | ||
634 | retval = amba_driver_register(&etb_driver); | 634 | retval = amba_driver_register(&etb_driver); |
635 | if (retval) { | 635 | if (retval) { |
636 | printk(KERN_ERR "Failed to register etb\n"); | 636 | pr_err("Failed to register etb\n"); |
637 | return retval; | 637 | return retval; |
638 | } | 638 | } |
639 | 639 | ||
640 | retval = amba_driver_register(&etm_driver); | 640 | retval = amba_driver_register(&etm_driver); |
641 | if (retval) { | 641 | if (retval) { |
642 | amba_driver_unregister(&etb_driver); | 642 | amba_driver_unregister(&etb_driver); |
643 | printk(KERN_ERR "Failed to probe etm\n"); | 643 | pr_err("Failed to probe etm\n"); |
644 | return retval; | 644 | return retval; |
645 | } | 645 | } |
646 | 646 | ||
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) | |||
124 | void release_fiq(struct fiq_handler *f) | 124 | void release_fiq(struct fiq_handler *f) |
125 | { | 125 | { |
126 | if (current_fiq != f) { | 126 | if (current_fiq != f) { |
127 | printk(KERN_ERR "%s FIQ trying to release %s FIQ\n", | 127 | pr_err("%s FIQ trying to release %s FIQ\n", |
128 | f->name, current_fiq->name); | 128 | f->name, current_fiq->name); |
129 | dump_stack(); | 129 | dump_stack(); |
130 | return; | 130 | return; |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index af9a8a927a4e..b8c75e45a950 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/ftrace.h> | 15 | #include <linux/ftrace.h> |
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/stop_machine.h> | ||
18 | 19 | ||
19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
20 | #include <asm/opcodes.h> | 21 | #include <asm/opcodes.h> |
@@ -35,6 +36,22 @@ | |||
35 | 36 | ||
36 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ | 37 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ |
37 | 38 | ||
39 | static int __ftrace_modify_code(void *data) | ||
40 | { | ||
41 | int *command = data; | ||
42 | |||
43 | set_kernel_text_rw(); | ||
44 | ftrace_modify_all_code(*command); | ||
45 | set_kernel_text_ro(); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | void arch_ftrace_update_code(int command) | ||
51 | { | ||
52 | stop_machine(__ftrace_modify_code, &command, NULL); | ||
53 | } | ||
54 | |||
38 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) | 55 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) |
39 | { | 56 | { |
40 | return rec->arch.old_mcount ? OLD_NOP : NOP; | 57 | return rec->arch.old_mcount ? OLD_NOP : NOP; |
@@ -73,6 +90,8 @@ int ftrace_arch_code_modify_prepare(void) | |||
73 | int ftrace_arch_code_modify_post_process(void) | 90 | int ftrace_arch_code_modify_post_process(void) |
74 | { | 91 | { |
75 | set_all_modules_text_ro(); | 92 | set_all_modules_text_ro(); |
93 | /* Make sure any TLB misses during machine stop are cleared. */ | ||
94 | flush_tlb_all(); | ||
76 | return 0; | 95 | return 0; |
77 | } | 96 | } |
78 | 97 | ||
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) | |||
51 | from++; | 51 | from++; |
52 | } | 52 | } |
53 | } | 53 | } |
54 | EXPORT_SYMBOL(_memcpy_fromio); | ||
54 | 55 | ||
55 | /* | 56 | /* |
56 | * Copy data from "real" memory space to IO memory space. | 57 | * 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) | |||
66 | to++; | 67 | to++; |
67 | } | 68 | } |
68 | } | 69 | } |
70 | EXPORT_SYMBOL(_memcpy_toio); | ||
69 | 71 | ||
70 | /* | 72 | /* |
71 | * "memset" on IO memory space. | 73 | * "memset" on IO memory space. |
@@ -79,7 +81,4 @@ void _memset_io(volatile void __iomem *dst, int c, size_t count) | |||
79 | dst++; | 81 | dst++; |
80 | } | 82 | } |
81 | } | 83 | } |
82 | |||
83 | EXPORT_SYMBOL(_memcpy_fromio); | ||
84 | EXPORT_SYMBOL(_memcpy_toio); | ||
85 | EXPORT_SYMBOL(_memset_io); | 84 | 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 @@ | |||
31 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #include <linux/ratelimit.h> | ||
34 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
35 | #include <linux/list.h> | 36 | #include <linux/list.h> |
36 | #include <linux/kallsyms.h> | 37 | #include <linux/kallsyms.h> |
@@ -82,7 +83,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) | |||
82 | unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; | 83 | unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; |
83 | 84 | ||
84 | if (irq >= nr_irqs) { | 85 | if (irq >= nr_irqs) { |
85 | printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); | 86 | pr_err("Trying to set irq flags for IRQ%d\n", irq); |
86 | return; | 87 | return; |
87 | } | 88 | } |
88 | 89 | ||
@@ -135,7 +136,6 @@ int __init arch_probe_nr_irqs(void) | |||
135 | #endif | 136 | #endif |
136 | 137 | ||
137 | #ifdef CONFIG_HOTPLUG_CPU | 138 | #ifdef CONFIG_HOTPLUG_CPU |
138 | |||
139 | static bool migrate_one_irq(struct irq_desc *desc) | 139 | static bool migrate_one_irq(struct irq_desc *desc) |
140 | { | 140 | { |
141 | struct irq_data *d = irq_desc_get_irq_data(desc); | 141 | struct irq_data *d = irq_desc_get_irq_data(desc); |
@@ -187,8 +187,8 @@ void migrate_irqs(void) | |||
187 | affinity_broken = migrate_one_irq(desc); | 187 | affinity_broken = migrate_one_irq(desc); |
188 | raw_spin_unlock(&desc->lock); | 188 | raw_spin_unlock(&desc->lock); |
189 | 189 | ||
190 | if (affinity_broken && printk_ratelimit()) | 190 | if (affinity_broken) |
191 | pr_warn("IRQ%u no longer affine to CPU%u\n", | 191 | pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n", |
192 | i, smp_processor_id()); | 192 | i, smp_processor_id()); |
193 | } | 193 | } |
194 | 194 | ||
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 @@ | |||
58 | #define MMX_SIZE (0x98) | 58 | #define MMX_SIZE (0x98) |
59 | 59 | ||
60 | .text | 60 | .text |
61 | .arm | ||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * Lazy switching of Concan coprocessor context | 64 | * Lazy switching of Concan coprocessor context |
@@ -182,6 +183,8 @@ concan_load: | |||
182 | tmcr wCon, r2 | 183 | tmcr wCon, r2 |
183 | ret lr | 184 | ret lr |
184 | 185 | ||
186 | ENDPROC(iwmmxt_task_enable) | ||
187 | |||
185 | /* | 188 | /* |
186 | * Back up Concan regs to save area and disable access to them | 189 | * Back up Concan regs to save area and disable access to them |
187 | * (mainly for gdb or sleep mode usage) | 190 | * (mainly for gdb or sleep mode usage) |
@@ -232,6 +235,8 @@ ENTRY(iwmmxt_task_disable) | |||
232 | 1: msr cpsr_c, ip @ restore interrupt mode | 235 | 1: msr cpsr_c, ip @ restore interrupt mode |
233 | ldmfd sp!, {r4, pc} | 236 | ldmfd sp!, {r4, pc} |
234 | 237 | ||
238 | ENDPROC(iwmmxt_task_disable) | ||
239 | |||
235 | /* | 240 | /* |
236 | * Copy Concan state to given memory address | 241 | * Copy Concan state to given memory address |
237 | * | 242 | * |
@@ -268,6 +273,8 @@ ENTRY(iwmmxt_task_copy) | |||
268 | msr cpsr_c, ip @ restore interrupt mode | 273 | msr cpsr_c, ip @ restore interrupt mode |
269 | ret r3 | 274 | ret r3 |
270 | 275 | ||
276 | ENDPROC(iwmmxt_task_copy) | ||
277 | |||
271 | /* | 278 | /* |
272 | * Restore Concan state from given memory address | 279 | * Restore Concan state from given memory address |
273 | * | 280 | * |
@@ -304,6 +311,8 @@ ENTRY(iwmmxt_task_restore) | |||
304 | msr cpsr_c, ip @ restore interrupt mode | 311 | msr cpsr_c, ip @ restore interrupt mode |
305 | ret r3 | 312 | ret r3 |
306 | 313 | ||
314 | ENDPROC(iwmmxt_task_restore) | ||
315 | |||
307 | /* | 316 | /* |
308 | * Concan handling on task switch | 317 | * Concan handling on task switch |
309 | * | 318 | * |
@@ -335,6 +344,8 @@ ENTRY(iwmmxt_task_switch) | |||
335 | mrc p15, 0, r1, c2, c0, 0 | 344 | mrc p15, 0, r1, c2, c0, 0 |
336 | sub pc, lr, r1, lsr #32 @ cpwait and return | 345 | sub pc, lr, r1, lsr #32 @ cpwait and return |
337 | 346 | ||
347 | ENDPROC(iwmmxt_task_switch) | ||
348 | |||
338 | /* | 349 | /* |
339 | * Remove Concan ownership of given task | 350 | * Remove Concan ownership of given task |
340 | * | 351 | * |
@@ -353,6 +364,8 @@ ENTRY(iwmmxt_task_release) | |||
353 | msr cpsr_c, r2 @ restore interrupts | 364 | msr cpsr_c, r2 @ restore interrupts |
354 | ret lr | 365 | ret lr |
355 | 366 | ||
367 | ENDPROC(iwmmxt_task_release) | ||
368 | |||
356 | .data | 369 | .data |
357 | concan_owner: | 370 | concan_owner: |
358 | .word 0 | 371 | .word 0 |
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index 4ce4f789446d..afeeb9ea6f43 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c | |||
@@ -19,7 +19,7 @@ static void __arch_jump_label_transform(struct jump_entry *entry, | |||
19 | insn = arm_gen_nop(); | 19 | insn = arm_gen_nop(); |
20 | 20 | ||
21 | if (is_static) | 21 | if (is_static) |
22 | __patch_text(addr, insn); | 22 | __patch_text_early(addr, insn); |
23 | else | 23 | else |
24 | patch_text(addr, insn); | 24 | patch_text(addr, insn); |
25 | } | 25 | } |
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index a74b53c1b7df..07db2f8a1b45 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -12,8 +12,12 @@ | |||
12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
13 | #include <linux/kdebug.h> | 13 | #include <linux/kdebug.h> |
14 | #include <linux/kgdb.h> | 14 | #include <linux/kgdb.h> |
15 | #include <linux/uaccess.h> | ||
16 | |||
15 | #include <asm/traps.h> | 17 | #include <asm/traps.h> |
16 | 18 | ||
19 | #include "patch.h" | ||
20 | |||
17 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 21 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = |
18 | { | 22 | { |
19 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, | 23 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, |
@@ -244,6 +248,31 @@ void kgdb_arch_exit(void) | |||
244 | unregister_die_notifier(&kgdb_notifier); | 248 | unregister_die_notifier(&kgdb_notifier); |
245 | } | 249 | } |
246 | 250 | ||
251 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
252 | { | ||
253 | int err; | ||
254 | |||
255 | /* patch_text() only supports int-sized breakpoints */ | ||
256 | BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE); | ||
257 | |||
258 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | ||
259 | BREAK_INSTR_SIZE); | ||
260 | if (err) | ||
261 | return err; | ||
262 | |||
263 | patch_text((void *)bpt->bpt_addr, | ||
264 | *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr); | ||
265 | |||
266 | return err; | ||
267 | } | ||
268 | |||
269 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
270 | { | ||
271 | patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
247 | /* | 276 | /* |
248 | * Register our undef instruction hooks with ARM undef core. | 277 | * Register our undef instruction hooks with ARM undef core. |
249 | * We regsiter a hook specifically looking for the KGB break inst | 278 | * We regsiter a hook specifically looking for the KGB break inst |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8cf0996aa1a8..de2b085ad753 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -29,6 +29,7 @@ extern unsigned long kexec_boot_atags; | |||
29 | 29 | ||
30 | static atomic_t waiting_for_crash_ipi; | 30 | static atomic_t waiting_for_crash_ipi; |
31 | 31 | ||
32 | static unsigned long dt_mem; | ||
32 | /* | 33 | /* |
33 | * Provide a dummy crash_notes definition while crash dump arrives to arm. | 34 | * Provide a dummy crash_notes definition while crash dump arrives to arm. |
34 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. | 35 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. |
@@ -64,7 +65,7 @@ int machine_kexec_prepare(struct kimage *image) | |||
64 | return err; | 65 | return err; |
65 | 66 | ||
66 | if (be32_to_cpu(header) == OF_DT_HEADER) | 67 | if (be32_to_cpu(header) == OF_DT_HEADER) |
67 | kexec_boot_atags = current_segment->mem; | 68 | dt_mem = current_segment->mem; |
68 | } | 69 | } |
69 | return 0; | 70 | return 0; |
70 | } | 71 | } |
@@ -126,12 +127,12 @@ void machine_crash_shutdown(struct pt_regs *regs) | |||
126 | msecs--; | 127 | msecs--; |
127 | } | 128 | } |
128 | if (atomic_read(&waiting_for_crash_ipi) > 0) | 129 | if (atomic_read(&waiting_for_crash_ipi) > 0) |
129 | printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); | 130 | pr_warn("Non-crashing CPUs did not react to IPI\n"); |
130 | 131 | ||
131 | crash_save_cpu(regs, smp_processor_id()); | 132 | crash_save_cpu(regs, smp_processor_id()); |
132 | machine_kexec_mask_interrupts(); | 133 | machine_kexec_mask_interrupts(); |
133 | 134 | ||
134 | printk(KERN_INFO "Loading crashdump kernel...\n"); | 135 | pr_info("Loading crashdump kernel...\n"); |
135 | } | 136 | } |
136 | 137 | ||
137 | /* | 138 | /* |
@@ -163,12 +164,12 @@ void machine_kexec(struct kimage *image) | |||
163 | reboot_code_buffer = page_address(image->control_code_page); | 164 | reboot_code_buffer = page_address(image->control_code_page); |
164 | 165 | ||
165 | /* Prepare parameters for reboot_code_buffer*/ | 166 | /* Prepare parameters for reboot_code_buffer*/ |
167 | set_kernel_text_rw(); | ||
166 | kexec_start_address = image->start; | 168 | kexec_start_address = image->start; |
167 | kexec_indirection_page = page_list; | 169 | kexec_indirection_page = page_list; |
168 | kexec_mach_type = machine_arch_type; | 170 | kexec_mach_type = machine_arch_type; |
169 | if (!kexec_boot_atags) | 171 | kexec_boot_atags = dt_mem ?: image->start - KEXEC_ARM_ZIMAGE_OFFSET |
170 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | 172 | + KEXEC_ARM_ATAGS_OFFSET; |
171 | |||
172 | 173 | ||
173 | /* copy our kernel relocation code to the control code page */ | 174 | /* copy our kernel relocation code to the control code page */ |
174 | reboot_entry = fncpy(reboot_code_buffer, | 175 | reboot_entry = fncpy(reboot_code_buffer, |
@@ -177,7 +178,7 @@ void machine_kexec(struct kimage *image) | |||
177 | reboot_entry_phys = (unsigned long)reboot_entry + | 178 | reboot_entry_phys = (unsigned long)reboot_entry + |
178 | (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); | 179 | (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); |
179 | 180 | ||
180 | printk(KERN_INFO "Bye!\n"); | 181 | pr_info("Bye!\n"); |
181 | 182 | ||
182 | if (kexec_reinit) | 183 | if (kexec_reinit) |
183 | kexec_reinit(); | 184 | 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, | |||
251 | #endif | 251 | #endif |
252 | 252 | ||
253 | default: | 253 | default: |
254 | printk(KERN_ERR "%s: unknown relocation: %u\n", | 254 | pr_err("%s: unknown relocation: %u\n", |
255 | module->name, ELF32_R_TYPE(rel->r_info)); | 255 | module->name, ELF32_R_TYPE(rel->r_info)); |
256 | return -ENOEXEC; | 256 | return -ENOEXEC; |
257 | } | 257 | } |
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 07314af47733..5038960e3c55 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c | |||
@@ -1,8 +1,11 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/spinlock.h> | ||
2 | #include <linux/kprobes.h> | 3 | #include <linux/kprobes.h> |
4 | #include <linux/mm.h> | ||
3 | #include <linux/stop_machine.h> | 5 | #include <linux/stop_machine.h> |
4 | 6 | ||
5 | #include <asm/cacheflush.h> | 7 | #include <asm/cacheflush.h> |
8 | #include <asm/fixmap.h> | ||
6 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
7 | #include <asm/opcodes.h> | 10 | #include <asm/opcodes.h> |
8 | 11 | ||
@@ -13,21 +16,77 @@ struct patch { | |||
13 | unsigned int insn; | 16 | unsigned int insn; |
14 | }; | 17 | }; |
15 | 18 | ||
16 | void __kprobes __patch_text(void *addr, unsigned int insn) | 19 | static DEFINE_SPINLOCK(patch_lock); |
20 | |||
21 | static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags) | ||
22 | __acquires(&patch_lock) | ||
23 | { | ||
24 | unsigned int uintaddr = (uintptr_t) addr; | ||
25 | bool module = !core_kernel_text(uintaddr); | ||
26 | struct page *page; | ||
27 | |||
28 | if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX)) | ||
29 | page = vmalloc_to_page(addr); | ||
30 | else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA)) | ||
31 | page = virt_to_page(addr); | ||
32 | else | ||
33 | return addr; | ||
34 | |||
35 | if (flags) | ||
36 | spin_lock_irqsave(&patch_lock, *flags); | ||
37 | else | ||
38 | __acquire(&patch_lock); | ||
39 | |||
40 | set_fixmap(fixmap, page_to_phys(page)); | ||
41 | |||
42 | return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); | ||
43 | } | ||
44 | |||
45 | static void __kprobes patch_unmap(int fixmap, unsigned long *flags) | ||
46 | __releases(&patch_lock) | ||
47 | { | ||
48 | clear_fixmap(fixmap); | ||
49 | |||
50 | if (flags) | ||
51 | spin_unlock_irqrestore(&patch_lock, *flags); | ||
52 | else | ||
53 | __release(&patch_lock); | ||
54 | } | ||
55 | |||
56 | void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap) | ||
17 | { | 57 | { |
18 | bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); | 58 | bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); |
59 | unsigned int uintaddr = (uintptr_t) addr; | ||
60 | bool twopage = false; | ||
61 | unsigned long flags; | ||
62 | void *waddr = addr; | ||
19 | int size; | 63 | int size; |
20 | 64 | ||
65 | if (remap) | ||
66 | waddr = patch_map(addr, FIX_TEXT_POKE0, &flags); | ||
67 | else | ||
68 | __acquire(&patch_lock); | ||
69 | |||
21 | if (thumb2 && __opcode_is_thumb16(insn)) { | 70 | if (thumb2 && __opcode_is_thumb16(insn)) { |
22 | *(u16 *)addr = __opcode_to_mem_thumb16(insn); | 71 | *(u16 *)waddr = __opcode_to_mem_thumb16(insn); |
23 | size = sizeof(u16); | 72 | size = sizeof(u16); |
24 | } else if (thumb2 && ((uintptr_t)addr & 2)) { | 73 | } else if (thumb2 && (uintaddr & 2)) { |
25 | u16 first = __opcode_thumb32_first(insn); | 74 | u16 first = __opcode_thumb32_first(insn); |
26 | u16 second = __opcode_thumb32_second(insn); | 75 | u16 second = __opcode_thumb32_second(insn); |
27 | u16 *addrh = addr; | 76 | u16 *addrh0 = waddr; |
77 | u16 *addrh1 = waddr + 2; | ||
78 | |||
79 | twopage = (uintaddr & ~PAGE_MASK) == PAGE_SIZE - 2; | ||
80 | if (twopage && remap) | ||
81 | addrh1 = patch_map(addr + 2, FIX_TEXT_POKE1, NULL); | ||
82 | |||
83 | *addrh0 = __opcode_to_mem_thumb16(first); | ||
84 | *addrh1 = __opcode_to_mem_thumb16(second); | ||
28 | 85 | ||
29 | addrh[0] = __opcode_to_mem_thumb16(first); | 86 | if (twopage && addrh1 != addr + 2) { |
30 | addrh[1] = __opcode_to_mem_thumb16(second); | 87 | flush_kernel_vmap_range(addrh1, 2); |
88 | patch_unmap(FIX_TEXT_POKE1, NULL); | ||
89 | } | ||
31 | 90 | ||
32 | size = sizeof(u32); | 91 | size = sizeof(u32); |
33 | } else { | 92 | } else { |
@@ -36,10 +95,16 @@ void __kprobes __patch_text(void *addr, unsigned int insn) | |||
36 | else | 95 | else |
37 | insn = __opcode_to_mem_arm(insn); | 96 | insn = __opcode_to_mem_arm(insn); |
38 | 97 | ||
39 | *(u32 *)addr = insn; | 98 | *(u32 *)waddr = insn; |
40 | size = sizeof(u32); | 99 | size = sizeof(u32); |
41 | } | 100 | } |
42 | 101 | ||
102 | if (waddr != addr) { | ||
103 | flush_kernel_vmap_range(waddr, twopage ? size / 2 : size); | ||
104 | patch_unmap(FIX_TEXT_POKE0, &flags); | ||
105 | } else | ||
106 | __release(&patch_lock); | ||
107 | |||
43 | flush_icache_range((uintptr_t)(addr), | 108 | flush_icache_range((uintptr_t)(addr), |
44 | (uintptr_t)(addr) + size); | 109 | (uintptr_t)(addr) + size); |
45 | } | 110 | } |
@@ -60,16 +125,5 @@ void __kprobes patch_text(void *addr, unsigned int insn) | |||
60 | .insn = insn, | 125 | .insn = insn, |
61 | }; | 126 | }; |
62 | 127 | ||
63 | if (cache_ops_need_broadcast()) { | 128 | stop_machine(patch_text_stop_machine, &patch, NULL); |
64 | stop_machine(patch_text_stop_machine, &patch, cpu_online_mask); | ||
65 | } else { | ||
66 | bool straddles_word = IS_ENABLED(CONFIG_THUMB2_KERNEL) | ||
67 | && __opcode_is_thumb32(insn) | ||
68 | && ((uintptr_t)addr & 2); | ||
69 | |||
70 | if (straddles_word) | ||
71 | stop_machine(patch_text_stop_machine, &patch, NULL); | ||
72 | else | ||
73 | __patch_text(addr, insn); | ||
74 | } | ||
75 | } | 129 | } |
diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h index b4731f2dac38..77e054c2f6cd 100644 --- a/arch/arm/kernel/patch.h +++ b/arch/arm/kernel/patch.h | |||
@@ -2,6 +2,16 @@ | |||
2 | #define _ARM_KERNEL_PATCH_H | 2 | #define _ARM_KERNEL_PATCH_H |
3 | 3 | ||
4 | void patch_text(void *addr, unsigned int insn); | 4 | void patch_text(void *addr, unsigned int insn); |
5 | void __patch_text(void *addr, unsigned int insn); | 5 | void __patch_text_real(void *addr, unsigned int insn, bool remap); |
6 | |||
7 | static inline void __patch_text(void *addr, unsigned int insn) | ||
8 | { | ||
9 | __patch_text_real(addr, insn, true); | ||
10 | } | ||
11 | |||
12 | static inline void __patch_text_early(void *addr, unsigned int insn) | ||
13 | { | ||
14 | __patch_text_real(addr, insn, false); | ||
15 | } | ||
6 | 16 | ||
7 | #endif | 17 | #endif |
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); | |||
51 | static const char *processor_modes[] __maybe_unused = { | 51 | static const char *processor_modes[] __maybe_unused = { |
52 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , | 52 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , |
53 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", | 53 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", |
54 | "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , | 54 | "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "MON_32" , "ABT_32" , |
55 | "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" | 55 | "UK8_32" , "UK9_32" , "HYP_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static const char *isa_modes[] __maybe_unused = { | 58 | 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) | |||
39 | { | 39 | { |
40 | struct return_address_data data; | 40 | struct return_address_data data; |
41 | struct stackframe frame; | 41 | struct stackframe frame; |
42 | register unsigned long current_sp asm ("sp"); | ||
43 | 42 | ||
44 | data.level = level + 2; | 43 | data.level = level + 2; |
45 | data.addr = NULL; | 44 | data.addr = NULL; |
46 | 45 | ||
47 | frame.fp = (unsigned long)__builtin_frame_address(0); | 46 | frame.fp = (unsigned long)__builtin_frame_address(0); |
48 | frame.sp = current_sp; | 47 | frame.sp = current_stack_pointer; |
49 | frame.lr = (unsigned long)__builtin_return_address(0); | 48 | frame.lr = (unsigned long)__builtin_return_address(0); |
50 | frame.pc = (unsigned long)return_address; | 49 | frame.pc = (unsigned long)return_address; |
51 | 50 | ||
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) | |||
900 | mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); | 900 | mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); |
901 | machine_desc = mdesc; | 901 | machine_desc = mdesc; |
902 | machine_name = mdesc->name; | 902 | machine_name = mdesc->name; |
903 | dump_stack_set_arch_desc("%s", mdesc->name); | ||
903 | 904 | ||
904 | if (mdesc->reboot_mode != REBOOT_HARD) | 905 | if (mdesc->reboot_mode != REBOOT_HARD) |
905 | reboot_mode = mdesc->reboot_mode; | 906 | 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) | |||
592 | } | 592 | } |
593 | syscall = 0; | 593 | syscall = 0; |
594 | } else if (thread_flags & _TIF_UPROBE) { | 594 | } else if (thread_flags & _TIF_UPROBE) { |
595 | clear_thread_flag(TIF_UPROBE); | ||
596 | uprobe_notify_resume(regs); | 595 | uprobe_notify_resume(regs); |
597 | } else { | 596 | } else { |
598 | clear_thread_flag(TIF_NOTIFY_RESUME); | 597 | 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) | |||
225 | pr_err("CPU%u: cpu didn't die\n", cpu); | 225 | pr_err("CPU%u: cpu didn't die\n", cpu); |
226 | return; | 226 | return; |
227 | } | 227 | } |
228 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | 228 | pr_notice("CPU%u: shutdown\n", cpu); |
229 | 229 | ||
230 | /* | 230 | /* |
231 | * platform_cpu_kill() is generally expected to do the powering off | 231 | * platform_cpu_kill() is generally expected to do the powering off |
@@ -235,7 +235,7 @@ void __cpu_die(unsigned int cpu) | |||
235 | * the requesting CPU and the dying CPU actually losing power. | 235 | * the requesting CPU and the dying CPU actually losing power. |
236 | */ | 236 | */ |
237 | if (!platform_cpu_kill(cpu)) | 237 | if (!platform_cpu_kill(cpu)) |
238 | printk("CPU%u: unable to kill\n", cpu); | 238 | pr_err("CPU%u: unable to kill\n", cpu); |
239 | } | 239 | } |
240 | 240 | ||
241 | /* | 241 | /* |
@@ -351,7 +351,7 @@ asmlinkage void secondary_start_kernel(void) | |||
351 | 351 | ||
352 | cpu_init(); | 352 | cpu_init(); |
353 | 353 | ||
354 | printk("CPU%u: Booted secondary processor\n", cpu); | 354 | pr_debug("CPU%u: Booted secondary processor\n", cpu); |
355 | 355 | ||
356 | preempt_disable(); | 356 | preempt_disable(); |
357 | trace_hardirqs_off(); | 357 | trace_hardirqs_off(); |
@@ -387,9 +387,6 @@ asmlinkage void secondary_start_kernel(void) | |||
387 | 387 | ||
388 | void __init smp_cpus_done(unsigned int max_cpus) | 388 | void __init smp_cpus_done(unsigned int max_cpus) |
389 | { | 389 | { |
390 | printk(KERN_INFO "SMP: Total of %d processors activated.\n", | ||
391 | num_online_cpus()); | ||
392 | |||
393 | hyp_mode_check(); | 390 | hyp_mode_check(); |
394 | } | 391 | } |
395 | 392 | ||
@@ -521,7 +518,7 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
521 | if (system_state == SYSTEM_BOOTING || | 518 | if (system_state == SYSTEM_BOOTING || |
522 | system_state == SYSTEM_RUNNING) { | 519 | system_state == SYSTEM_RUNNING) { |
523 | raw_spin_lock(&stop_lock); | 520 | raw_spin_lock(&stop_lock); |
524 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); | 521 | pr_crit("CPU%u: stopping\n", cpu); |
525 | dump_stack(); | 522 | dump_stack(); |
526 | raw_spin_unlock(&stop_lock); | 523 | raw_spin_unlock(&stop_lock); |
527 | } | 524 | } |
@@ -615,8 +612,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
615 | break; | 612 | break; |
616 | 613 | ||
617 | default: | 614 | default: |
618 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", | 615 | pr_crit("CPU%u: Unknown IPI message 0x%x\n", |
619 | cpu, ipinr); | 616 | cpu, ipinr); |
620 | break; | 617 | break; |
621 | } | 618 | } |
622 | 619 | ||
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) | |||
199 | * the timer ticks | 199 | * the timer ticks |
200 | */ | 200 | */ |
201 | if (twd_timer_rate == 0) { | 201 | if (twd_timer_rate == 0) { |
202 | printk(KERN_INFO "Calibrating local timer... "); | 202 | pr_info("Calibrating local timer... "); |
203 | 203 | ||
204 | /* Wait for a tick to start */ | 204 | /* Wait for a tick to start */ |
205 | waitjiffies = get_jiffies_64() + 1; | 205 | waitjiffies = get_jiffies_64() + 1; |
@@ -223,7 +223,7 @@ static void twd_calibrate_rate(void) | |||
223 | 223 | ||
224 | twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); | 224 | twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); |
225 | 225 | ||
226 | printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, | 226 | pr_cont("%lu.%02luMHz.\n", twd_timer_rate / 1000000, |
227 | (twd_timer_rate / 10000) % 100); | 227 | (twd_timer_rate / 10000) % 100); |
228 | } | 228 | } |
229 | } | 229 | } |
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, | |||
134 | frame.pc = thread_saved_pc(tsk); | 134 | frame.pc = thread_saved_pc(tsk); |
135 | #endif | 135 | #endif |
136 | } else { | 136 | } else { |
137 | register unsigned long current_sp asm ("sp"); | ||
138 | |||
139 | /* We don't want this function nor the caller */ | 137 | /* We don't want this function nor the caller */ |
140 | data.skip += 2; | 138 | data.skip += 2; |
141 | frame.fp = (unsigned long)__builtin_frame_address(0); | 139 | frame.fp = (unsigned long)__builtin_frame_address(0); |
142 | frame.sp = current_sp; | 140 | frame.sp = current_stack_pointer; |
143 | frame.lr = (unsigned long)__builtin_return_address(0); | 141 | frame.lr = (unsigned long)__builtin_return_address(0); |
144 | frame.pc = (unsigned long)__save_stack_trace; | 142 | frame.pc = (unsigned long)__save_stack_trace; |
145 | } | 143 | } |
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) | |||
260 | return -ENOMEM; | 260 | return -ENOMEM; |
261 | #endif /* CONFIG_PROC_FS */ | 261 | #endif /* CONFIG_PROC_FS */ |
262 | 262 | ||
263 | printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); | 263 | pr_notice("Registering SWP/SWPB emulation handler\n"); |
264 | register_undef_hook(&swp_hook); | 264 | register_undef_hook(&swp_hook); |
265 | 265 | ||
266 | return 0; | 266 | 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) | |||
72 | if ((pfr0 & 0x0000f000) != 0x00001000) | 72 | if ((pfr0 & 0x0000f000) != 0x00001000) |
73 | return 0; | 73 | return 0; |
74 | 74 | ||
75 | printk(KERN_INFO "ThumbEE CPU extension supported.\n"); | 75 | pr_info("ThumbEE CPU extension supported.\n"); |
76 | elf_hwcap |= HWCAP_THUMBEE; | 76 | elf_hwcap |= HWCAP_THUMBEE; |
77 | thread_register_notifier(&thumbee_notifier_block); | 77 | thread_register_notifier(&thumbee_notifier_block); |
78 | 78 | ||
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) | |||
165 | 165 | ||
166 | set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); | 166 | set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); |
167 | 167 | ||
168 | printk(KERN_INFO "CPU%u: update cpu_capacity %lu\n", | 168 | pr_info("CPU%u: update cpu_capacity %lu\n", |
169 | cpu, arch_scale_cpu_capacity(NULL, cpu)); | 169 | cpu, arch_scale_cpu_capacity(NULL, cpu)); |
170 | } | 170 | } |
171 | 171 | ||
@@ -269,7 +269,7 @@ void store_cpu_topology(unsigned int cpuid) | |||
269 | 269 | ||
270 | update_cpu_capacity(cpuid); | 270 | update_cpu_capacity(cpuid); |
271 | 271 | ||
272 | printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", | 272 | pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", |
273 | cpuid, cpu_topology[cpuid].thread_id, | 273 | cpuid, cpu_topology[cpuid].thread_id, |
274 | cpu_topology[cpuid].core_id, | 274 | cpu_topology[cpuid].core_id, |
275 | cpu_topology[cpuid].socket_id, mpidr); | 275 | 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) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | if (!fp) { | 200 | if (!fp) { |
201 | printk("no frame pointer"); | 201 | pr_cont("no frame pointer"); |
202 | ok = 0; | 202 | ok = 0; |
203 | } else if (verify_stack(fp)) { | 203 | } else if (verify_stack(fp)) { |
204 | printk("invalid frame pointer 0x%08x", fp); | 204 | pr_cont("invalid frame pointer 0x%08x", fp); |
205 | ok = 0; | 205 | ok = 0; |
206 | } else if (fp < (unsigned long)end_of_stack(tsk)) | 206 | } else if (fp < (unsigned long)end_of_stack(tsk)) |
207 | printk("frame pointer underflow"); | 207 | pr_cont("frame pointer underflow"); |
208 | printk("\n"); | 208 | pr_cont("\n"); |
209 | 209 | ||
210 | if (ok) | 210 | if (ok) |
211 | c_backtrace(fp, mode); | 211 | c_backtrace(fp, mode); |
@@ -240,8 +240,8 @@ static int __die(const char *str, int err, struct pt_regs *regs) | |||
240 | static int die_counter; | 240 | static int die_counter; |
241 | int ret; | 241 | int ret; |
242 | 242 | ||
243 | printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP | 243 | pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP S_ISA "\n", |
244 | S_ISA "\n", str, err, ++die_counter); | 244 | str, err, ++die_counter); |
245 | 245 | ||
246 | /* trap and error numbers are mostly meaningless on ARM */ | 246 | /* trap and error numbers are mostly meaningless on ARM */ |
247 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); | 247 | 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) | |||
250 | 250 | ||
251 | print_modules(); | 251 | print_modules(); |
252 | __show_regs(regs); | 252 | __show_regs(regs); |
253 | printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", | 253 | pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", |
254 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); | 254 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); |
255 | 255 | ||
256 | if (!user_mode(regs) || in_interrupt()) { | 256 | if (!user_mode(regs) || in_interrupt()) { |
257 | dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, | 257 | dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, |
@@ -446,7 +446,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
446 | die_sig: | 446 | die_sig: |
447 | #ifdef CONFIG_DEBUG_USER | 447 | #ifdef CONFIG_DEBUG_USER |
448 | if (user_debug & UDBG_UNDEFINED) { | 448 | if (user_debug & UDBG_UNDEFINED) { |
449 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", | 449 | pr_info("%s (%d): undefined instruction: pc=%p\n", |
450 | current->comm, task_pid_nr(current), pc); | 450 | current->comm, task_pid_nr(current), pc); |
451 | __show_regs(regs); | 451 | __show_regs(regs); |
452 | dump_instr(KERN_INFO, regs); | 452 | dump_instr(KERN_INFO, regs); |
@@ -496,7 +496,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) | |||
496 | { | 496 | { |
497 | console_verbose(); | 497 | console_verbose(); |
498 | 498 | ||
499 | printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]); | 499 | pr_crit("Bad mode in %s handler detected\n", handler[reason]); |
500 | 500 | ||
501 | die("Oops - bad mode", regs, 0); | 501 | die("Oops - bad mode", regs, 0); |
502 | local_irq_disable(); | 502 | local_irq_disable(); |
@@ -516,7 +516,7 @@ static int bad_syscall(int n, struct pt_regs *regs) | |||
516 | 516 | ||
517 | #ifdef CONFIG_DEBUG_USER | 517 | #ifdef CONFIG_DEBUG_USER |
518 | if (user_debug & UDBG_SYSCALL) { | 518 | if (user_debug & UDBG_SYSCALL) { |
519 | printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", | 519 | pr_err("[%d] %s: obsolete system call %08x.\n", |
520 | task_pid_nr(current), current->comm, n); | 520 | task_pid_nr(current), current->comm, n); |
521 | dump_instr(KERN_ERR, regs); | 521 | dump_instr(KERN_ERR, regs); |
522 | } | 522 | } |
@@ -694,7 +694,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) | |||
694 | * something catastrophic has happened | 694 | * something catastrophic has happened |
695 | */ | 695 | */ |
696 | if (user_debug & UDBG_SYSCALL) { | 696 | if (user_debug & UDBG_SYSCALL) { |
697 | printk("[%d] %s: arm syscall %d\n", | 697 | pr_err("[%d] %s: arm syscall %d\n", |
698 | task_pid_nr(current), current->comm, no); | 698 | task_pid_nr(current), current->comm, no); |
699 | dump_instr("", regs); | 699 | dump_instr("", regs); |
700 | if (user_mode(regs)) { | 700 | if (user_mode(regs)) { |
@@ -753,8 +753,8 @@ late_initcall(arm_mrc_hook_init); | |||
753 | 753 | ||
754 | void __bad_xchg(volatile void *ptr, int size) | 754 | void __bad_xchg(volatile void *ptr, int size) |
755 | { | 755 | { |
756 | printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", | 756 | pr_err("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", |
757 | __builtin_return_address(0), ptr, size); | 757 | __builtin_return_address(0), ptr, size); |
758 | BUG(); | 758 | BUG(); |
759 | } | 759 | } |
760 | EXPORT_SYMBOL(__bad_xchg); | 760 | EXPORT_SYMBOL(__bad_xchg); |
@@ -771,8 +771,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) | |||
771 | 771 | ||
772 | #ifdef CONFIG_DEBUG_USER | 772 | #ifdef CONFIG_DEBUG_USER |
773 | if (user_debug & UDBG_BADABORT) { | 773 | if (user_debug & UDBG_BADABORT) { |
774 | printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n", | 774 | pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n", |
775 | task_pid_nr(current), current->comm, code, instr); | 775 | task_pid_nr(current), current->comm, code, instr); |
776 | dump_instr(KERN_ERR, regs); | 776 | dump_instr(KERN_ERR, regs); |
777 | show_pte(current->mm, addr); | 777 | show_pte(current->mm, addr); |
778 | } | 778 | } |
@@ -788,29 +788,29 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) | |||
788 | 788 | ||
789 | void __readwrite_bug(const char *fn) | 789 | void __readwrite_bug(const char *fn) |
790 | { | 790 | { |
791 | printk("%s called, but not implemented\n", fn); | 791 | pr_err("%s called, but not implemented\n", fn); |
792 | BUG(); | 792 | BUG(); |
793 | } | 793 | } |
794 | EXPORT_SYMBOL(__readwrite_bug); | 794 | EXPORT_SYMBOL(__readwrite_bug); |
795 | 795 | ||
796 | void __pte_error(const char *file, int line, pte_t pte) | 796 | void __pte_error(const char *file, int line, pte_t pte) |
797 | { | 797 | { |
798 | printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); | 798 | pr_err("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); |
799 | } | 799 | } |
800 | 800 | ||
801 | void __pmd_error(const char *file, int line, pmd_t pmd) | 801 | void __pmd_error(const char *file, int line, pmd_t pmd) |
802 | { | 802 | { |
803 | printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); | 803 | pr_err("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); |
804 | } | 804 | } |
805 | 805 | ||
806 | void __pgd_error(const char *file, int line, pgd_t pgd) | 806 | void __pgd_error(const char *file, int line, pgd_t pgd) |
807 | { | 807 | { |
808 | printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); | 808 | pr_err("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); |
809 | } | 809 | } |
810 | 810 | ||
811 | asmlinkage void __div0(void) | 811 | asmlinkage void __div0(void) |
812 | { | 812 | { |
813 | printk("Division by zero in kernel.\n"); | 813 | pr_err("Division by zero in kernel.\n"); |
814 | dump_stack(); | 814 | dump_stack(); |
815 | } | 815 | } |
816 | EXPORT_SYMBOL(__div0); | 816 | 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) | |||
471 | void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 471 | void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
472 | { | 472 | { |
473 | struct stackframe frame; | 473 | struct stackframe frame; |
474 | register unsigned long current_sp asm ("sp"); | ||
475 | 474 | ||
476 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); | 475 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); |
477 | 476 | ||
@@ -485,7 +484,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
485 | frame.pc = regs->ARM_lr; | 484 | frame.pc = regs->ARM_lr; |
486 | } else if (tsk == current) { | 485 | } else if (tsk == current) { |
487 | frame.fp = (unsigned long)__builtin_frame_address(0); | 486 | frame.fp = (unsigned long)__builtin_frame_address(0); |
488 | frame.sp = current_sp; | 487 | frame.sp = current_stack_pointer; |
489 | frame.lr = (unsigned long)__builtin_return_address(0); | 488 | frame.lr = (unsigned long)__builtin_return_address(0); |
490 | frame.pc = (unsigned long)unwind_backtrace; | 489 | frame.pc = (unsigned long)unwind_backtrace; |
491 | } else { | 490 | } else { |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 8e95aa47457a..b31aa73e8076 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -8,6 +8,9 @@ | |||
8 | #include <asm/thread_info.h> | 8 | #include <asm/thread_info.h> |
9 | #include <asm/memory.h> | 9 | #include <asm/memory.h> |
10 | #include <asm/page.h> | 10 | #include <asm/page.h> |
11 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
12 | #include <asm/pgtable.h> | ||
13 | #endif | ||
11 | 14 | ||
12 | #define PROC_INFO \ | 15 | #define PROC_INFO \ |
13 | . = ALIGN(4); \ | 16 | . = ALIGN(4); \ |
@@ -90,6 +93,11 @@ SECTIONS | |||
90 | _text = .; | 93 | _text = .; |
91 | HEAD_TEXT | 94 | HEAD_TEXT |
92 | } | 95 | } |
96 | |||
97 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
98 | . = ALIGN(1<<SECTION_SHIFT); | ||
99 | #endif | ||
100 | |||
93 | .text : { /* Real text segment */ | 101 | .text : { /* Real text segment */ |
94 | _stext = .; /* Text and read-only data */ | 102 | _stext = .; /* Text and read-only data */ |
95 | __exception_text_start = .; | 103 | __exception_text_start = .; |
@@ -112,6 +120,9 @@ SECTIONS | |||
112 | ARM_CPU_KEEP(PROC_INFO) | 120 | ARM_CPU_KEEP(PROC_INFO) |
113 | } | 121 | } |
114 | 122 | ||
123 | #ifdef CONFIG_DEBUG_RODATA | ||
124 | . = ALIGN(1<<SECTION_SHIFT); | ||
125 | #endif | ||
115 | RO_DATA(PAGE_SIZE) | 126 | RO_DATA(PAGE_SIZE) |
116 | 127 | ||
117 | . = ALIGN(4); | 128 | . = ALIGN(4); |
@@ -145,7 +156,11 @@ SECTIONS | |||
145 | _etext = .; /* End of text and rodata section */ | 156 | _etext = .; /* End of text and rodata section */ |
146 | 157 | ||
147 | #ifndef CONFIG_XIP_KERNEL | 158 | #ifndef CONFIG_XIP_KERNEL |
159 | # ifdef CONFIG_ARM_KERNMEM_PERMS | ||
160 | . = ALIGN(1<<SECTION_SHIFT); | ||
161 | # else | ||
148 | . = ALIGN(PAGE_SIZE); | 162 | . = ALIGN(PAGE_SIZE); |
163 | # endif | ||
149 | __init_begin = .; | 164 | __init_begin = .; |
150 | #endif | 165 | #endif |
151 | /* | 166 | /* |
@@ -219,7 +234,11 @@ SECTIONS | |||
219 | __data_loc = ALIGN(4); /* location in binary */ | 234 | __data_loc = ALIGN(4); /* location in binary */ |
220 | . = PAGE_OFFSET + TEXT_OFFSET; | 235 | . = PAGE_OFFSET + TEXT_OFFSET; |
221 | #else | 236 | #else |
237 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
238 | . = ALIGN(1<<SECTION_SHIFT); | ||
239 | #else | ||
222 | . = ALIGN(THREAD_SIZE); | 240 | . = ALIGN(THREAD_SIZE); |
241 | #endif | ||
223 | __init_end = .; | 242 | __init_end = .; |
224 | __data_loc = .; | 243 | __data_loc = .; |
225 | #endif | 244 | #endif |
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) | |||
157 | 157 | ||
158 | if (cpu_has_iwmmxt()) { | 158 | if (cpu_has_iwmmxt()) { |
159 | #ifndef CONFIG_IWMMXT | 159 | #ifndef CONFIG_IWMMXT |
160 | printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " | 160 | pr_warn("CAUTION: XScale iWMMXt coprocessor detected, but kernel support is missing.\n"); |
161 | "detected, but kernel support is missing.\n"); | ||
162 | #else | 161 | #else |
163 | printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); | 162 | pr_info("XScale iWMMXt coprocessor detected.\n"); |
164 | elf_hwcap |= HWCAP_IWMMXT; | 163 | elf_hwcap |= HWCAP_IWMMXT; |
165 | thread_register_notifier(&iwmmxt_notifier_block); | 164 | thread_register_notifier(&iwmmxt_notifier_block); |
166 | #endif | 165 | #endif |
167 | } else { | 166 | } else { |
168 | printk(KERN_INFO "XScale DSP coprocessor detected.\n"); | 167 | pr_info("XScale DSP coprocessor detected.\n"); |
169 | thread_register_notifier(&dsp_notifier_block); | 168 | thread_register_notifier(&dsp_notifier_block); |
170 | cp_access |= 1; | 169 | cp_access |= 1; |
171 | } | 170 | } |
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 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Prototype: | 18 | * Prototype: |
@@ -77,6 +78,10 @@ | |||
77 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} | 78 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} |
78 | .endm | 79 | .endm |
79 | 80 | ||
81 | .macro usave reg1 reg2 | ||
82 | UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) | ||
83 | .endm | ||
84 | |||
80 | .macro exit reg1 reg2 | 85 | .macro exit reg1 reg2 |
81 | add sp, sp, #8 | 86 | add sp, sp, #8 |
82 | ldmfd sp!, {r0, \reg1, \reg2} | 87 | 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 @@ | |||
53 | * data as needed by the implementation including this code. Called | 53 | * data as needed by the implementation including this code. Called |
54 | * upon code entry. | 54 | * upon code entry. |
55 | * | 55 | * |
56 | * usave reg1 reg2 | ||
57 | * | ||
58 | * Unwind annotation macro is corresponding for 'enter' macro. | ||
59 | * It tell unwinder that preserved some provided registers on the stack | ||
60 | * and additional data by a prior 'enter' macro. | ||
61 | * | ||
56 | * exit reg1 reg2 | 62 | * exit reg1 reg2 |
57 | * | 63 | * |
58 | * Restore registers with the values previously saved with the | 64 | * Restore registers with the values previously saved with the |
@@ -67,7 +73,12 @@ | |||
67 | */ | 73 | */ |
68 | 74 | ||
69 | 75 | ||
76 | UNWIND( .fnstart ) | ||
70 | enter r4, lr | 77 | enter r4, lr |
78 | UNWIND( .fnend ) | ||
79 | |||
80 | UNWIND( .fnstart ) | ||
81 | usave r4, lr @ in first stmdb block | ||
71 | 82 | ||
72 | subs r2, r2, #4 | 83 | subs r2, r2, #4 |
73 | blt 8f | 84 | blt 8f |
@@ -79,6 +90,11 @@ | |||
79 | 90 | ||
80 | 1: subs r2, r2, #(28) | 91 | 1: subs r2, r2, #(28) |
81 | stmfd sp!, {r5 - r8} | 92 | stmfd sp!, {r5 - r8} |
93 | UNWIND( .fnend ) | ||
94 | |||
95 | UNWIND( .fnstart ) | ||
96 | usave r4, lr | ||
97 | UNWIND( .save {r5 - r8} ) @ in second stmfd block | ||
82 | blt 5f | 98 | blt 5f |
83 | 99 | ||
84 | CALGN( ands ip, r0, #31 ) | 100 | CALGN( ands ip, r0, #31 ) |
@@ -144,7 +160,10 @@ | |||
144 | CALGN( bcs 2b ) | 160 | CALGN( bcs 2b ) |
145 | 161 | ||
146 | 7: ldmfd sp!, {r5 - r8} | 162 | 7: ldmfd sp!, {r5 - r8} |
163 | UNWIND( .fnend ) @ end of second stmfd block | ||
147 | 164 | ||
165 | UNWIND( .fnstart ) | ||
166 | usave r4, lr @ still in first stmdb block | ||
148 | 8: movs r2, r2, lsl #31 | 167 | 8: movs r2, r2, lsl #31 |
149 | ldr1b r1, r3, ne, abort=21f | 168 | ldr1b r1, r3, ne, abort=21f |
150 | ldr1b r1, r4, cs, abort=21f | 169 | ldr1b r1, r4, cs, abort=21f |
@@ -173,10 +192,13 @@ | |||
173 | ldr1w r1, lr, abort=21f | 192 | ldr1w r1, lr, abort=21f |
174 | beq 17f | 193 | beq 17f |
175 | bgt 18f | 194 | bgt 18f |
195 | UNWIND( .fnend ) | ||
176 | 196 | ||
177 | 197 | ||
178 | .macro forward_copy_shift pull push | 198 | .macro forward_copy_shift pull push |
179 | 199 | ||
200 | UNWIND( .fnstart ) | ||
201 | usave r4, lr @ still in first stmdb block | ||
180 | subs r2, r2, #28 | 202 | subs r2, r2, #28 |
181 | blt 14f | 203 | blt 14f |
182 | 204 | ||
@@ -187,7 +209,11 @@ | |||
187 | CALGN( bcc 15f ) | 209 | CALGN( bcc 15f ) |
188 | 210 | ||
189 | 11: stmfd sp!, {r5 - r9} | 211 | 11: stmfd sp!, {r5 - r9} |
212 | UNWIND( .fnend ) | ||
190 | 213 | ||
214 | UNWIND( .fnstart ) | ||
215 | usave r4, lr | ||
216 | UNWIND( .save {r5 - r9} ) @ in new second stmfd block | ||
191 | PLD( pld [r1, #0] ) | 217 | PLD( pld [r1, #0] ) |
192 | PLD( subs r2, r2, #96 ) | 218 | PLD( subs r2, r2, #96 ) |
193 | PLD( pld [r1, #28] ) | 219 | PLD( pld [r1, #28] ) |
@@ -221,7 +247,10 @@ | |||
221 | PLD( bge 13b ) | 247 | PLD( bge 13b ) |
222 | 248 | ||
223 | ldmfd sp!, {r5 - r9} | 249 | ldmfd sp!, {r5 - r9} |
250 | UNWIND( .fnend ) @ end of the second stmfd block | ||
224 | 251 | ||
252 | UNWIND( .fnstart ) | ||
253 | usave r4, lr @ still in first stmdb block | ||
225 | 14: ands ip, r2, #28 | 254 | 14: ands ip, r2, #28 |
226 | beq 16f | 255 | beq 16f |
227 | 256 | ||
@@ -236,6 +265,7 @@ | |||
236 | 265 | ||
237 | 16: sub r1, r1, #(\push / 8) | 266 | 16: sub r1, r1, #(\push / 8) |
238 | b 8b | 267 | b 8b |
268 | UNWIND( .fnend ) | ||
239 | 269 | ||
240 | .endm | 270 | .endm |
241 | 271 | ||
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 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Prototype: | 18 | * Prototype: |
@@ -80,6 +81,10 @@ | |||
80 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} | 81 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} |
81 | .endm | 82 | .endm |
82 | 83 | ||
84 | .macro usave reg1 reg2 | ||
85 | UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) | ||
86 | .endm | ||
87 | |||
83 | .macro exit reg1 reg2 | 88 | .macro exit reg1 reg2 |
84 | add sp, sp, #8 | 89 | add sp, sp, #8 |
85 | ldmfd sp!, {r0, \reg1, \reg2} | 90 | 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 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | #define LDR1W_SHIFT 0 | 17 | #define LDR1W_SHIFT 0 |
17 | #define STR1W_SHIFT 0 | 18 | #define STR1W_SHIFT 0 |
@@ -48,6 +49,10 @@ | |||
48 | stmdb sp!, {r0, \reg1, \reg2} | 49 | stmdb sp!, {r0, \reg1, \reg2} |
49 | .endm | 50 | .endm |
50 | 51 | ||
52 | .macro usave reg1 reg2 | ||
53 | UNWIND( .save {r0, \reg1, \reg2} ) | ||
54 | .endm | ||
55 | |||
51 | .macro exit reg1 reg2 | 56 | .macro exit reg1 reg2 |
52 | ldmfd sp!, {r0, \reg1, \reg2} | 57 | ldmfd sp!, {r0, \reg1, \reg2} |
53 | .endm | 58 | .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 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | .text | 17 | .text |
17 | 18 | ||
@@ -27,12 +28,17 @@ | |||
27 | */ | 28 | */ |
28 | 29 | ||
29 | ENTRY(memmove) | 30 | ENTRY(memmove) |
31 | UNWIND( .fnstart ) | ||
30 | 32 | ||
31 | subs ip, r0, r1 | 33 | subs ip, r0, r1 |
32 | cmphi r2, ip | 34 | cmphi r2, ip |
33 | bls memcpy | 35 | bls memcpy |
34 | 36 | ||
35 | stmfd sp!, {r0, r4, lr} | 37 | stmfd sp!, {r0, r4, lr} |
38 | UNWIND( .fnend ) | ||
39 | |||
40 | UNWIND( .fnstart ) | ||
41 | UNWIND( .save {r0, r4, lr} ) @ in first stmfd block | ||
36 | add r1, r1, r2 | 42 | add r1, r1, r2 |
37 | add r0, r0, r2 | 43 | add r0, r0, r2 |
38 | subs r2, r2, #4 | 44 | subs r2, r2, #4 |
@@ -45,6 +51,11 @@ ENTRY(memmove) | |||
45 | 51 | ||
46 | 1: subs r2, r2, #(28) | 52 | 1: subs r2, r2, #(28) |
47 | stmfd sp!, {r5 - r8} | 53 | stmfd sp!, {r5 - r8} |
54 | UNWIND( .fnend ) | ||
55 | |||
56 | UNWIND( .fnstart ) | ||
57 | UNWIND( .save {r0, r4, lr} ) | ||
58 | UNWIND( .save {r5 - r8} ) @ in second stmfd block | ||
48 | blt 5f | 59 | blt 5f |
49 | 60 | ||
50 | CALGN( ands ip, r0, #31 ) | 61 | CALGN( ands ip, r0, #31 ) |
@@ -97,6 +108,10 @@ ENTRY(memmove) | |||
97 | CALGN( bcs 2b ) | 108 | CALGN( bcs 2b ) |
98 | 109 | ||
99 | 7: ldmfd sp!, {r5 - r8} | 110 | 7: ldmfd sp!, {r5 - r8} |
111 | UNWIND( .fnend ) @ end of second stmfd block | ||
112 | |||
113 | UNWIND( .fnstart ) | ||
114 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
100 | 115 | ||
101 | 8: movs r2, r2, lsl #31 | 116 | 8: movs r2, r2, lsl #31 |
102 | ldrneb r3, [r1, #-1]! | 117 | ldrneb r3, [r1, #-1]! |
@@ -124,10 +139,13 @@ ENTRY(memmove) | |||
124 | ldr r3, [r1, #0] | 139 | ldr r3, [r1, #0] |
125 | beq 17f | 140 | beq 17f |
126 | blt 18f | 141 | blt 18f |
142 | UNWIND( .fnend ) | ||
127 | 143 | ||
128 | 144 | ||
129 | .macro backward_copy_shift push pull | 145 | .macro backward_copy_shift push pull |
130 | 146 | ||
147 | UNWIND( .fnstart ) | ||
148 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
131 | subs r2, r2, #28 | 149 | subs r2, r2, #28 |
132 | blt 14f | 150 | blt 14f |
133 | 151 | ||
@@ -137,6 +155,11 @@ ENTRY(memmove) | |||
137 | CALGN( bcc 15f ) | 155 | CALGN( bcc 15f ) |
138 | 156 | ||
139 | 11: stmfd sp!, {r5 - r9} | 157 | 11: stmfd sp!, {r5 - r9} |
158 | UNWIND( .fnend ) | ||
159 | |||
160 | UNWIND( .fnstart ) | ||
161 | UNWIND( .save {r0, r4, lr} ) | ||
162 | UNWIND( .save {r5 - r9} ) @ in new second stmfd block | ||
140 | 163 | ||
141 | PLD( pld [r1, #-4] ) | 164 | PLD( pld [r1, #-4] ) |
142 | PLD( subs r2, r2, #96 ) | 165 | PLD( subs r2, r2, #96 ) |
@@ -171,6 +194,10 @@ ENTRY(memmove) | |||
171 | PLD( bge 13b ) | 194 | PLD( bge 13b ) |
172 | 195 | ||
173 | ldmfd sp!, {r5 - r9} | 196 | ldmfd sp!, {r5 - r9} |
197 | UNWIND( .fnend ) @ end of the second stmfd block | ||
198 | |||
199 | UNWIND( .fnstart ) | ||
200 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
174 | 201 | ||
175 | 14: ands ip, r2, #28 | 202 | 14: ands ip, r2, #28 |
176 | beq 16f | 203 | beq 16f |
@@ -186,6 +213,7 @@ ENTRY(memmove) | |||
186 | 213 | ||
187 | 16: add r1, r1, #(\pull / 8) | 214 | 16: add r1, r1, #(\pull / 8) |
188 | b 8b | 215 | b 8b |
216 | UNWIND( .fnend ) | ||
189 | 217 | ||
190 | .endm | 218 | .endm |
191 | 219 | ||
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 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
13 | #include <asm/assembler.h> | 13 | #include <asm/assembler.h> |
14 | #include <asm/unwind.h> | ||
14 | 15 | ||
15 | .text | 16 | .text |
16 | .align 5 | 17 | .align 5 |
17 | 18 | ||
18 | ENTRY(memset) | 19 | ENTRY(memset) |
20 | UNWIND( .fnstart ) | ||
19 | ands r3, r0, #3 @ 1 unaligned? | 21 | ands r3, r0, #3 @ 1 unaligned? |
20 | mov ip, r0 @ preserve r0 as return value | 22 | mov ip, r0 @ preserve r0 as return value |
21 | bne 6f @ 1 | 23 | bne 6f @ 1 |
@@ -34,6 +36,9 @@ ENTRY(memset) | |||
34 | * We need 2 extra registers for this loop - use r8 and the LR | 36 | * We need 2 extra registers for this loop - use r8 and the LR |
35 | */ | 37 | */ |
36 | stmfd sp!, {r8, lr} | 38 | stmfd sp!, {r8, lr} |
39 | UNWIND( .fnend ) | ||
40 | UNWIND( .fnstart ) | ||
41 | UNWIND( .save {r8, lr} ) | ||
37 | mov r8, r1 | 42 | mov r8, r1 |
38 | mov lr, r1 | 43 | mov lr, r1 |
39 | 44 | ||
@@ -53,6 +58,7 @@ ENTRY(memset) | |||
53 | tst r2, #16 | 58 | tst r2, #16 |
54 | stmneia ip!, {r1, r3, r8, lr} | 59 | stmneia ip!, {r1, r3, r8, lr} |
55 | ldmfd sp!, {r8, lr} | 60 | ldmfd sp!, {r8, lr} |
61 | UNWIND( .fnend ) | ||
56 | 62 | ||
57 | #else | 63 | #else |
58 | 64 | ||
@@ -62,6 +68,9 @@ ENTRY(memset) | |||
62 | */ | 68 | */ |
63 | 69 | ||
64 | stmfd sp!, {r4-r8, lr} | 70 | stmfd sp!, {r4-r8, lr} |
71 | UNWIND( .fnend ) | ||
72 | UNWIND( .fnstart ) | ||
73 | UNWIND( .save {r4-r8, lr} ) | ||
65 | mov r4, r1 | 74 | mov r4, r1 |
66 | mov r5, r1 | 75 | mov r5, r1 |
67 | mov r6, r1 | 76 | mov r6, r1 |
@@ -94,9 +103,11 @@ ENTRY(memset) | |||
94 | tst r2, #16 | 103 | tst r2, #16 |
95 | stmneia ip!, {r4-r7} | 104 | stmneia ip!, {r4-r7} |
96 | ldmfd sp!, {r4-r8, lr} | 105 | ldmfd sp!, {r4-r8, lr} |
106 | UNWIND( .fnend ) | ||
97 | 107 | ||
98 | #endif | 108 | #endif |
99 | 109 | ||
110 | UNWIND( .fnstart ) | ||
100 | 4: tst r2, #8 | 111 | 4: tst r2, #8 |
101 | stmneia ip!, {r1, r3} | 112 | stmneia ip!, {r1, r3} |
102 | tst r2, #4 | 113 | tst r2, #4 |
@@ -120,4 +131,5 @@ ENTRY(memset) | |||
120 | strb r1, [ip], #1 @ 1 | 131 | strb r1, [ip], #1 @ 1 |
121 | add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) | 132 | add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) |
122 | b 1b | 133 | b 1b |
134 | UNWIND( .fnend ) | ||
123 | ENDPROC(memset) | 135 | 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 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/linkage.h> | 10 | #include <linux/linkage.h> |
11 | #include <asm/assembler.h> | 11 | #include <asm/assembler.h> |
12 | #include <asm/unwind.h> | ||
12 | 13 | ||
13 | .text | 14 | .text |
14 | .align 5 | 15 | .align 5 |
@@ -18,6 +19,7 @@ | |||
18 | * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we | 19 | * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we |
19 | * don't bother; we use byte stores instead. | 20 | * don't bother; we use byte stores instead. |
20 | */ | 21 | */ |
22 | UNWIND( .fnstart ) | ||
21 | 1: subs r1, r1, #4 @ 1 do we have enough | 23 | 1: subs r1, r1, #4 @ 1 do we have enough |
22 | blt 5f @ 1 bytes to align with? | 24 | blt 5f @ 1 bytes to align with? |
23 | cmp r3, #2 @ 1 | 25 | cmp r3, #2 @ 1 |
@@ -47,6 +49,9 @@ ENTRY(__memzero) | |||
47 | * use the LR | 49 | * use the LR |
48 | */ | 50 | */ |
49 | str lr, [sp, #-4]! @ 1 | 51 | str lr, [sp, #-4]! @ 1 |
52 | UNWIND( .fnend ) | ||
53 | UNWIND( .fnstart ) | ||
54 | UNWIND( .save {lr} ) | ||
50 | mov ip, r2 @ 1 | 55 | mov ip, r2 @ 1 |
51 | mov lr, r2 @ 1 | 56 | mov lr, r2 @ 1 |
52 | 57 | ||
@@ -66,6 +71,7 @@ ENTRY(__memzero) | |||
66 | tst r1, #16 @ 1 16 bytes or more? | 71 | tst r1, #16 @ 1 16 bytes or more? |
67 | stmneia r0!, {r2, r3, ip, lr} @ 4 | 72 | stmneia r0!, {r2, r3, ip, lr} @ 4 |
68 | ldr lr, [sp], #4 @ 1 | 73 | ldr lr, [sp], #4 @ 1 |
74 | UNWIND( .fnend ) | ||
69 | 75 | ||
70 | #else | 76 | #else |
71 | 77 | ||
@@ -75,6 +81,9 @@ ENTRY(__memzero) | |||
75 | */ | 81 | */ |
76 | 82 | ||
77 | stmfd sp!, {r4-r7, lr} | 83 | stmfd sp!, {r4-r7, lr} |
84 | UNWIND( .fnend ) | ||
85 | UNWIND( .fnstart ) | ||
86 | UNWIND( .save {r4-r7, lr} ) | ||
78 | mov r4, r2 | 87 | mov r4, r2 |
79 | mov r5, r2 | 88 | mov r5, r2 |
80 | mov r6, r2 | 89 | mov r6, r2 |
@@ -105,9 +114,11 @@ ENTRY(__memzero) | |||
105 | tst r1, #16 | 114 | tst r1, #16 |
106 | stmneia r0!, {r4-r7} | 115 | stmneia r0!, {r4-r7} |
107 | ldmfd sp!, {r4-r7, lr} | 116 | ldmfd sp!, {r4-r7, lr} |
117 | UNWIND( .fnend ) | ||
108 | 118 | ||
109 | #endif | 119 | #endif |
110 | 120 | ||
121 | UNWIND( .fnstart ) | ||
111 | 4: tst r1, #8 @ 1 8 bytes or more? | 122 | 4: tst r1, #8 @ 1 8 bytes or more? |
112 | stmneia r0!, {r2, r3} @ 2 | 123 | stmneia r0!, {r2, r3} @ 2 |
113 | tst r1, #4 @ 1 4 bytes or more? | 124 | tst r1, #4 @ 1 4 bytes or more? |
@@ -122,4 +133,5 @@ ENTRY(__memzero) | |||
122 | tst r1, #1 @ 1 a byte left over | 133 | tst r1, #1 @ 1 a byte left over |
123 | strneb r2, [r0], #1 @ 1 | 134 | strneb r2, [r0], #1 @ 1 |
124 | ret lr @ 1 | 135 | ret lr @ 1 |
136 | UNWIND( .fnend ) | ||
125 | ENDPROC(__memzero) | 137 | 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 @@ | |||
15 | #include <linux/clkdev.h> | 15 | #include <linux/clkdev.h> |
16 | 16 | ||
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | #include <mach/generic.h> | ||
18 | 19 | ||
19 | struct clkops { | 20 | struct clkops { |
20 | void (*enable)(struct clk *); | 21 | void (*enable)(struct clk *); |
21 | void (*disable)(struct clk *); | 22 | void (*disable)(struct clk *); |
23 | unsigned long (*get_rate)(struct clk *); | ||
22 | }; | 24 | }; |
23 | 25 | ||
24 | struct clk { | 26 | struct clk { |
@@ -33,13 +35,6 @@ struct clk clk_##_name = { \ | |||
33 | 35 | ||
34 | static DEFINE_SPINLOCK(clocks_lock); | 36 | static DEFINE_SPINLOCK(clocks_lock); |
35 | 37 | ||
36 | /* Dummy clk routine to build generic kernel parts that may be using them */ | ||
37 | unsigned long clk_get_rate(struct clk *clk) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | EXPORT_SYMBOL(clk_get_rate); | ||
42 | |||
43 | static void clk_gpio27_enable(struct clk *clk) | 38 | static void clk_gpio27_enable(struct clk *clk) |
44 | { | 39 | { |
45 | /* | 40 | /* |
@@ -58,6 +53,19 @@ static void clk_gpio27_disable(struct clk *clk) | |||
58 | GAFR &= ~GPIO_32_768kHz; | 53 | GAFR &= ~GPIO_32_768kHz; |
59 | } | 54 | } |
60 | 55 | ||
56 | static void clk_cpu_enable(struct clk *clk) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static void clk_cpu_disable(struct clk *clk) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | static unsigned long clk_cpu_get_rate(struct clk *clk) | ||
65 | { | ||
66 | return sa11x0_getspeed(0) * 1000; | ||
67 | } | ||
68 | |||
61 | int clk_enable(struct clk *clk) | 69 | int clk_enable(struct clk *clk) |
62 | { | 70 | { |
63 | unsigned long flags; | 71 | unsigned long flags; |
@@ -87,16 +95,37 @@ void clk_disable(struct clk *clk) | |||
87 | } | 95 | } |
88 | EXPORT_SYMBOL(clk_disable); | 96 | EXPORT_SYMBOL(clk_disable); |
89 | 97 | ||
98 | unsigned long clk_get_rate(struct clk *clk) | ||
99 | { | ||
100 | if (clk && clk->ops && clk->ops->get_rate) | ||
101 | return clk->ops->get_rate(clk); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL(clk_get_rate); | ||
106 | |||
90 | const struct clkops clk_gpio27_ops = { | 107 | const struct clkops clk_gpio27_ops = { |
91 | .enable = clk_gpio27_enable, | 108 | .enable = clk_gpio27_enable, |
92 | .disable = clk_gpio27_disable, | 109 | .disable = clk_gpio27_disable, |
93 | }; | 110 | }; |
94 | 111 | ||
112 | const struct clkops clk_cpu_ops = { | ||
113 | .enable = clk_cpu_enable, | ||
114 | .disable = clk_cpu_disable, | ||
115 | .get_rate = clk_cpu_get_rate, | ||
116 | }; | ||
117 | |||
95 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); | 118 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); |
96 | 119 | ||
120 | static DEFINE_CLK(cpu, &clk_cpu_ops); | ||
121 | |||
97 | static struct clk_lookup sa11xx_clkregs[] = { | 122 | static struct clk_lookup sa11xx_clkregs[] = { |
98 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), | 123 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), |
99 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), | 124 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), |
125 | CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu), | ||
126 | CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu), | ||
127 | /* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */ | ||
128 | CLKDEV_INIT("1800", NULL, &clk_cpu), | ||
100 | }; | 129 | }; |
101 | 130 | ||
102 | static int __init sa11xx_clk_init(void) | 131 | 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 @@ | |||
30 | #include <linux/gpio_keys.h> | 30 | #include <linux/gpio_keys.h> |
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/pda_power.h> | 33 | #include <linux/power/gpio-charger.h> |
34 | 34 | ||
35 | #include <video/sa1100fb.h> | 35 | #include <video/sa1100fb.h> |
36 | 36 | ||
@@ -131,62 +131,24 @@ static struct irda_platform_data collie_ir_data = { | |||
131 | /* | 131 | /* |
132 | * Collie AC IN | 132 | * Collie AC IN |
133 | */ | 133 | */ |
134 | static int collie_power_init(struct device *dev) | ||
135 | { | ||
136 | int ret = gpio_request(COLLIE_GPIO_AC_IN, "ac in"); | ||
137 | if (ret) | ||
138 | goto err_gpio_req; | ||
139 | |||
140 | ret = gpio_direction_input(COLLIE_GPIO_AC_IN); | ||
141 | if (ret) | ||
142 | goto err_gpio_in; | ||
143 | |||
144 | return 0; | ||
145 | |||
146 | err_gpio_in: | ||
147 | gpio_free(COLLIE_GPIO_AC_IN); | ||
148 | err_gpio_req: | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static void collie_power_exit(struct device *dev) | ||
153 | { | ||
154 | gpio_free(COLLIE_GPIO_AC_IN); | ||
155 | } | ||
156 | |||
157 | static int collie_power_ac_online(void) | ||
158 | { | ||
159 | return gpio_get_value(COLLIE_GPIO_AC_IN) == 2; | ||
160 | } | ||
161 | |||
162 | static char *collie_ac_supplied_to[] = { | 134 | static char *collie_ac_supplied_to[] = { |
163 | "main-battery", | 135 | "main-battery", |
164 | "backup-battery", | 136 | "backup-battery", |
165 | }; | 137 | }; |
166 | 138 | ||
167 | static struct pda_power_pdata collie_power_data = { | 139 | |
168 | .init = collie_power_init, | 140 | static struct gpio_charger_platform_data collie_power_data = { |
169 | .is_ac_online = collie_power_ac_online, | 141 | .name = "charger", |
170 | .exit = collie_power_exit, | 142 | .type = POWER_SUPPLY_TYPE_MAINS, |
143 | .gpio = COLLIE_GPIO_AC_IN, | ||
171 | .supplied_to = collie_ac_supplied_to, | 144 | .supplied_to = collie_ac_supplied_to, |
172 | .num_supplicants = ARRAY_SIZE(collie_ac_supplied_to), | 145 | .num_supplicants = ARRAY_SIZE(collie_ac_supplied_to), |
173 | }; | 146 | }; |
174 | 147 | ||
175 | static struct resource collie_power_resource[] = { | ||
176 | { | ||
177 | .name = "ac", | ||
178 | .flags = IORESOURCE_IRQ | | ||
179 | IORESOURCE_IRQ_HIGHEDGE | | ||
180 | IORESOURCE_IRQ_LOWEDGE, | ||
181 | }, | ||
182 | }; | ||
183 | |||
184 | static struct platform_device collie_power_device = { | 148 | static struct platform_device collie_power_device = { |
185 | .name = "pda-power", | 149 | .name = "gpio-charger", |
186 | .id = -1, | 150 | .id = -1, |
187 | .dev.platform_data = &collie_power_data, | 151 | .dev.platform_data = &collie_power_data, |
188 | .resource = collie_power_resource, | ||
189 | .num_resources = ARRAY_SIZE(collie_power_resource), | ||
190 | }; | 152 | }; |
191 | 153 | ||
192 | #ifdef CONFIG_SHARP_LOCOMO | 154 | #ifdef CONFIG_SHARP_LOCOMO |
@@ -420,9 +382,6 @@ static void __init collie_init(void) | |||
420 | 382 | ||
421 | GPSR |= _COLLIE_GPIO_UCB1x00_RESET; | 383 | GPSR |= _COLLIE_GPIO_UCB1x00_RESET; |
422 | 384 | ||
423 | collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN); | ||
424 | collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN); | ||
425 | |||
426 | sa11x0_ppc_configure_mcp(); | 385 | sa11x0_ppc_configure_mcp(); |
427 | 386 | ||
428 | 387 | ||
diff --git a/arch/arm/mach-sa1100/include/mach/entry-macro.S b/arch/arm/mach-sa1100/include/mach/entry-macro.S deleted file mode 100644 index 8cf7630bf024..000000000000 --- a/arch/arm/mach-sa1100/include/mach/entry-macro.S +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-sa1100/include/mach/entry-macro.S | ||
3 | * | ||
4 | * Low-level IRQ helper macros for SA1100-based platforms | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | .macro get_irqnr_preamble, base, tmp | ||
12 | mov \base, #0xfa000000 @ ICIP = 0xfa050000 | ||
13 | add \base, \base, #0x00050000 | ||
14 | .endm | ||
15 | |||
16 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
17 | ldr \irqstat, [\base] @ get irqs | ||
18 | ldr \irqnr, [\base, #4] @ ICMR = 0xfa050004 | ||
19 | ands \irqstat, \irqstat, \irqnr | ||
20 | mov \irqnr, #0 | ||
21 | beq 1001f | ||
22 | tst \irqstat, #0xff | ||
23 | moveq \irqstat, \irqstat, lsr #8 | ||
24 | addeq \irqnr, \irqnr, #8 | ||
25 | tsteq \irqstat, #0xff | ||
26 | moveq \irqstat, \irqstat, lsr #8 | ||
27 | addeq \irqnr, \irqnr, #8 | ||
28 | tsteq \irqstat, #0xff | ||
29 | moveq \irqstat, \irqstat, lsr #8 | ||
30 | addeq \irqnr, \irqnr, #8 | ||
31 | tst \irqstat, #0x0f | ||
32 | moveq \irqstat, \irqstat, lsr #4 | ||
33 | addeq \irqnr, \irqnr, #4 | ||
34 | tst \irqstat, #0x03 | ||
35 | moveq \irqstat, \irqstat, lsr #2 | ||
36 | addeq \irqnr, \irqnr, #2 | ||
37 | tst \irqstat, #0x01 | ||
38 | addeqs \irqnr, \irqnr, #1 | ||
39 | 1001: | ||
40 | .endm | ||
41 | |||
diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h index 3790298b7142..de0983494c7e 100644 --- a/arch/arm/mach-sa1100/include/mach/irqs.h +++ b/arch/arm/mach-sa1100/include/mach/irqs.h | |||
@@ -8,56 +8,56 @@ | |||
8 | * 2001/11/14 RMK Cleaned up and standardised a lot of the IRQs. | 8 | * 2001/11/14 RMK Cleaned up and standardised a lot of the IRQs. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define IRQ_GPIO0 0 | 11 | #define IRQ_GPIO0 1 |
12 | #define IRQ_GPIO1 1 | 12 | #define IRQ_GPIO1 2 |
13 | #define IRQ_GPIO2 2 | 13 | #define IRQ_GPIO2 3 |
14 | #define IRQ_GPIO3 3 | 14 | #define IRQ_GPIO3 4 |
15 | #define IRQ_GPIO4 4 | 15 | #define IRQ_GPIO4 5 |
16 | #define IRQ_GPIO5 5 | 16 | #define IRQ_GPIO5 6 |
17 | #define IRQ_GPIO6 6 | 17 | #define IRQ_GPIO6 7 |
18 | #define IRQ_GPIO7 7 | 18 | #define IRQ_GPIO7 8 |
19 | #define IRQ_GPIO8 8 | 19 | #define IRQ_GPIO8 9 |
20 | #define IRQ_GPIO9 9 | 20 | #define IRQ_GPIO9 10 |
21 | #define IRQ_GPIO10 10 | 21 | #define IRQ_GPIO10 11 |
22 | #define IRQ_GPIO11_27 11 | 22 | #define IRQ_GPIO11_27 12 |
23 | #define IRQ_LCD 12 /* LCD controller */ | 23 | #define IRQ_LCD 13 /* LCD controller */ |
24 | #define IRQ_Ser0UDC 13 /* Ser. port 0 UDC */ | 24 | #define IRQ_Ser0UDC 14 /* Ser. port 0 UDC */ |
25 | #define IRQ_Ser1SDLC 14 /* Ser. port 1 SDLC */ | 25 | #define IRQ_Ser1SDLC 15 /* Ser. port 1 SDLC */ |
26 | #define IRQ_Ser1UART 15 /* Ser. port 1 UART */ | 26 | #define IRQ_Ser1UART 16 /* Ser. port 1 UART */ |
27 | #define IRQ_Ser2ICP 16 /* Ser. port 2 ICP */ | 27 | #define IRQ_Ser2ICP 17 /* Ser. port 2 ICP */ |
28 | #define IRQ_Ser3UART 17 /* Ser. port 3 UART */ | 28 | #define IRQ_Ser3UART 18 /* Ser. port 3 UART */ |
29 | #define IRQ_Ser4MCP 18 /* Ser. port 4 MCP */ | 29 | #define IRQ_Ser4MCP 19 /* Ser. port 4 MCP */ |
30 | #define IRQ_Ser4SSP 19 /* Ser. port 4 SSP */ | 30 | #define IRQ_Ser4SSP 20 /* Ser. port 4 SSP */ |
31 | #define IRQ_DMA0 20 /* DMA controller channel 0 */ | 31 | #define IRQ_DMA0 21 /* DMA controller channel 0 */ |
32 | #define IRQ_DMA1 21 /* DMA controller channel 1 */ | 32 | #define IRQ_DMA1 22 /* DMA controller channel 1 */ |
33 | #define IRQ_DMA2 22 /* DMA controller channel 2 */ | 33 | #define IRQ_DMA2 23 /* DMA controller channel 2 */ |
34 | #define IRQ_DMA3 23 /* DMA controller channel 3 */ | 34 | #define IRQ_DMA3 24 /* DMA controller channel 3 */ |
35 | #define IRQ_DMA4 24 /* DMA controller channel 4 */ | 35 | #define IRQ_DMA4 25 /* DMA controller channel 4 */ |
36 | #define IRQ_DMA5 25 /* DMA controller channel 5 */ | 36 | #define IRQ_DMA5 26 /* DMA controller channel 5 */ |
37 | #define IRQ_OST0 26 /* OS Timer match 0 */ | 37 | #define IRQ_OST0 27 /* OS Timer match 0 */ |
38 | #define IRQ_OST1 27 /* OS Timer match 1 */ | 38 | #define IRQ_OST1 28 /* OS Timer match 1 */ |
39 | #define IRQ_OST2 28 /* OS Timer match 2 */ | 39 | #define IRQ_OST2 29 /* OS Timer match 2 */ |
40 | #define IRQ_OST3 29 /* OS Timer match 3 */ | 40 | #define IRQ_OST3 30 /* OS Timer match 3 */ |
41 | #define IRQ_RTC1Hz 30 /* RTC 1 Hz clock */ | 41 | #define IRQ_RTC1Hz 31 /* RTC 1 Hz clock */ |
42 | #define IRQ_RTCAlrm 31 /* RTC Alarm */ | 42 | #define IRQ_RTCAlrm 32 /* RTC Alarm */ |
43 | 43 | ||
44 | #define IRQ_GPIO11 32 | 44 | #define IRQ_GPIO11 33 |
45 | #define IRQ_GPIO12 33 | 45 | #define IRQ_GPIO12 34 |
46 | #define IRQ_GPIO13 34 | 46 | #define IRQ_GPIO13 35 |
47 | #define IRQ_GPIO14 35 | 47 | #define IRQ_GPIO14 36 |
48 | #define IRQ_GPIO15 36 | 48 | #define IRQ_GPIO15 37 |
49 | #define IRQ_GPIO16 37 | 49 | #define IRQ_GPIO16 38 |
50 | #define IRQ_GPIO17 38 | 50 | #define IRQ_GPIO17 39 |
51 | #define IRQ_GPIO18 39 | 51 | #define IRQ_GPIO18 40 |
52 | #define IRQ_GPIO19 40 | 52 | #define IRQ_GPIO19 41 |
53 | #define IRQ_GPIO20 41 | 53 | #define IRQ_GPIO20 42 |
54 | #define IRQ_GPIO21 42 | 54 | #define IRQ_GPIO21 43 |
55 | #define IRQ_GPIO22 43 | 55 | #define IRQ_GPIO22 44 |
56 | #define IRQ_GPIO23 44 | 56 | #define IRQ_GPIO23 45 |
57 | #define IRQ_GPIO24 45 | 57 | #define IRQ_GPIO24 46 |
58 | #define IRQ_GPIO25 46 | 58 | #define IRQ_GPIO25 47 |
59 | #define IRQ_GPIO26 47 | 59 | #define IRQ_GPIO26 48 |
60 | #define IRQ_GPIO27 48 | 60 | #define IRQ_GPIO27 49 |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * The next 16 interrupts are for board specific purposes. Since | 63 | * The next 16 interrupts are for board specific purposes. Since |
@@ -65,8 +65,8 @@ | |||
65 | * these. If you need more, increase IRQ_BOARD_END, but keep it | 65 | * these. If you need more, increase IRQ_BOARD_END, but keep it |
66 | * within sensible limits. IRQs 49 to 64 are available. | 66 | * within sensible limits. IRQs 49 to 64 are available. |
67 | */ | 67 | */ |
68 | #define IRQ_BOARD_START 49 | 68 | #define IRQ_BOARD_START 50 |
69 | #define IRQ_BOARD_END 65 | 69 | #define IRQ_BOARD_END 66 |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Figure out the MAX IRQ number. | 72 | * Figure out the MAX IRQ number. |
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index 2124f1fc2fbe..63e2901db416 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c | |||
@@ -14,17 +14,73 @@ | |||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/irqdomain.h> | ||
17 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
18 | #include <linux/syscore_ops.h> | 19 | #include <linux/syscore_ops.h> |
19 | 20 | ||
20 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
21 | #include <mach/irqs.h> | 22 | #include <mach/irqs.h> |
22 | #include <asm/mach/irq.h> | 23 | #include <asm/mach/irq.h> |
24 | #include <asm/exception.h> | ||
23 | 25 | ||
24 | #include "generic.h" | 26 | #include "generic.h" |
25 | 27 | ||
26 | 28 | ||
27 | /* | 29 | /* |
30 | * We don't need to ACK IRQs on the SA1100 unless they're GPIOs | ||
31 | * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm. | ||
32 | */ | ||
33 | static void sa1100_mask_irq(struct irq_data *d) | ||
34 | { | ||
35 | ICMR &= ~BIT(d->hwirq); | ||
36 | } | ||
37 | |||
38 | static void sa1100_unmask_irq(struct irq_data *d) | ||
39 | { | ||
40 | ICMR |= BIT(d->hwirq); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Apart form GPIOs, only the RTC alarm can be a wakeup event. | ||
45 | */ | ||
46 | static int sa1100_set_wake(struct irq_data *d, unsigned int on) | ||
47 | { | ||
48 | if (BIT(d->hwirq) == IC_RTCAlrm) { | ||
49 | if (on) | ||
50 | PWER |= PWER_RTC; | ||
51 | else | ||
52 | PWER &= ~PWER_RTC; | ||
53 | return 0; | ||
54 | } | ||
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | static struct irq_chip sa1100_normal_chip = { | ||
59 | .name = "SC", | ||
60 | .irq_ack = sa1100_mask_irq, | ||
61 | .irq_mask = sa1100_mask_irq, | ||
62 | .irq_unmask = sa1100_unmask_irq, | ||
63 | .irq_set_wake = sa1100_set_wake, | ||
64 | }; | ||
65 | |||
66 | static int sa1100_normal_irqdomain_map(struct irq_domain *d, | ||
67 | unsigned int irq, irq_hw_number_t hwirq) | ||
68 | { | ||
69 | irq_set_chip_and_handler(irq, &sa1100_normal_chip, | ||
70 | handle_level_irq); | ||
71 | set_irq_flags(irq, IRQF_VALID); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static struct irq_domain_ops sa1100_normal_irqdomain_ops = { | ||
77 | .map = sa1100_normal_irqdomain_map, | ||
78 | .xlate = irq_domain_xlate_onetwocell, | ||
79 | }; | ||
80 | |||
81 | static struct irq_domain *sa1100_normal_irqdomain; | ||
82 | |||
83 | /* | ||
28 | * SA1100 GPIO edge detection for IRQs: | 84 | * SA1100 GPIO edge detection for IRQs: |
29 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | 85 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. |
30 | * Use this instead of directly setting GRER/GFER. | 86 | * Use this instead of directly setting GRER/GFER. |
@@ -33,20 +89,11 @@ static int GPIO_IRQ_rising_edge; | |||
33 | static int GPIO_IRQ_falling_edge; | 89 | static int GPIO_IRQ_falling_edge; |
34 | static int GPIO_IRQ_mask = (1 << 11) - 1; | 90 | static int GPIO_IRQ_mask = (1 << 11) - 1; |
35 | 91 | ||
36 | /* | ||
37 | * To get the GPIO number from an IRQ number | ||
38 | */ | ||
39 | #define GPIO_11_27_IRQ(i) ((i) - 21) | ||
40 | #define GPIO11_27_MASK(irq) (1 << GPIO_11_27_IRQ(irq)) | ||
41 | |||
42 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | 92 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) |
43 | { | 93 | { |
44 | unsigned int mask; | 94 | unsigned int mask; |
45 | 95 | ||
46 | if (d->irq <= 10) | 96 | mask = BIT(d->hwirq); |
47 | mask = 1 << d->irq; | ||
48 | else | ||
49 | mask = GPIO11_27_MASK(d->irq); | ||
50 | 97 | ||
51 | if (type == IRQ_TYPE_PROBE) { | 98 | if (type == IRQ_TYPE_PROBE) { |
52 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) | 99 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) |
@@ -70,41 +117,51 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | |||
70 | } | 117 | } |
71 | 118 | ||
72 | /* | 119 | /* |
73 | * GPIO IRQs must be acknowledged. This is for IRQs from 0 to 10. | 120 | * GPIO IRQs must be acknowledged. |
74 | */ | 121 | */ |
75 | static void sa1100_low_gpio_ack(struct irq_data *d) | 122 | static void sa1100_gpio_ack(struct irq_data *d) |
76 | { | ||
77 | GEDR = (1 << d->irq); | ||
78 | } | ||
79 | |||
80 | static void sa1100_low_gpio_mask(struct irq_data *d) | ||
81 | { | ||
82 | ICMR &= ~(1 << d->irq); | ||
83 | } | ||
84 | |||
85 | static void sa1100_low_gpio_unmask(struct irq_data *d) | ||
86 | { | 123 | { |
87 | ICMR |= 1 << d->irq; | 124 | GEDR = BIT(d->hwirq); |
88 | } | 125 | } |
89 | 126 | ||
90 | static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on) | 127 | static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) |
91 | { | 128 | { |
92 | if (on) | 129 | if (on) |
93 | PWER |= 1 << d->irq; | 130 | PWER |= BIT(d->hwirq); |
94 | else | 131 | else |
95 | PWER &= ~(1 << d->irq); | 132 | PWER &= ~BIT(d->hwirq); |
96 | return 0; | 133 | return 0; |
97 | } | 134 | } |
98 | 135 | ||
136 | /* | ||
137 | * This is for IRQs from 0 to 10. | ||
138 | */ | ||
99 | static struct irq_chip sa1100_low_gpio_chip = { | 139 | static struct irq_chip sa1100_low_gpio_chip = { |
100 | .name = "GPIO-l", | 140 | .name = "GPIO-l", |
101 | .irq_ack = sa1100_low_gpio_ack, | 141 | .irq_ack = sa1100_gpio_ack, |
102 | .irq_mask = sa1100_low_gpio_mask, | 142 | .irq_mask = sa1100_mask_irq, |
103 | .irq_unmask = sa1100_low_gpio_unmask, | 143 | .irq_unmask = sa1100_unmask_irq, |
104 | .irq_set_type = sa1100_gpio_type, | 144 | .irq_set_type = sa1100_gpio_type, |
105 | .irq_set_wake = sa1100_low_gpio_wake, | 145 | .irq_set_wake = sa1100_gpio_wake, |
146 | }; | ||
147 | |||
148 | static int sa1100_low_gpio_irqdomain_map(struct irq_domain *d, | ||
149 | unsigned int irq, irq_hw_number_t hwirq) | ||
150 | { | ||
151 | irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip, | ||
152 | handle_edge_irq); | ||
153 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct irq_domain_ops sa1100_low_gpio_irqdomain_ops = { | ||
159 | .map = sa1100_low_gpio_irqdomain_map, | ||
160 | .xlate = irq_domain_xlate_onetwocell, | ||
106 | }; | 161 | }; |
107 | 162 | ||
163 | static struct irq_domain *sa1100_low_gpio_irqdomain; | ||
164 | |||
108 | /* | 165 | /* |
109 | * IRQ11 (GPIO11 through 27) handler. We enter here with the | 166 | * IRQ11 (GPIO11 through 27) handler. We enter here with the |
110 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ | 167 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ |
@@ -141,16 +198,9 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) | |||
141 | * In addition, the IRQs are all collected up into one bit in the | 198 | * In addition, the IRQs are all collected up into one bit in the |
142 | * interrupt controller registers. | 199 | * interrupt controller registers. |
143 | */ | 200 | */ |
144 | static void sa1100_high_gpio_ack(struct irq_data *d) | ||
145 | { | ||
146 | unsigned int mask = GPIO11_27_MASK(d->irq); | ||
147 | |||
148 | GEDR = mask; | ||
149 | } | ||
150 | |||
151 | static void sa1100_high_gpio_mask(struct irq_data *d) | 201 | static void sa1100_high_gpio_mask(struct irq_data *d) |
152 | { | 202 | { |
153 | unsigned int mask = GPIO11_27_MASK(d->irq); | 203 | unsigned int mask = BIT(d->hwirq); |
154 | 204 | ||
155 | GPIO_IRQ_mask &= ~mask; | 205 | GPIO_IRQ_mask &= ~mask; |
156 | 206 | ||
@@ -160,7 +210,7 @@ static void sa1100_high_gpio_mask(struct irq_data *d) | |||
160 | 210 | ||
161 | static void sa1100_high_gpio_unmask(struct irq_data *d) | 211 | static void sa1100_high_gpio_unmask(struct irq_data *d) |
162 | { | 212 | { |
163 | unsigned int mask = GPIO11_27_MASK(d->irq); | 213 | unsigned int mask = BIT(d->hwirq); |
164 | 214 | ||
165 | GPIO_IRQ_mask |= mask; | 215 | GPIO_IRQ_mask |= mask; |
166 | 216 | ||
@@ -168,61 +218,32 @@ static void sa1100_high_gpio_unmask(struct irq_data *d) | |||
168 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | 218 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; |
169 | } | 219 | } |
170 | 220 | ||
171 | static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on) | ||
172 | { | ||
173 | if (on) | ||
174 | PWER |= GPIO11_27_MASK(d->irq); | ||
175 | else | ||
176 | PWER &= ~GPIO11_27_MASK(d->irq); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct irq_chip sa1100_high_gpio_chip = { | 221 | static struct irq_chip sa1100_high_gpio_chip = { |
181 | .name = "GPIO-h", | 222 | .name = "GPIO-h", |
182 | .irq_ack = sa1100_high_gpio_ack, | 223 | .irq_ack = sa1100_gpio_ack, |
183 | .irq_mask = sa1100_high_gpio_mask, | 224 | .irq_mask = sa1100_high_gpio_mask, |
184 | .irq_unmask = sa1100_high_gpio_unmask, | 225 | .irq_unmask = sa1100_high_gpio_unmask, |
185 | .irq_set_type = sa1100_gpio_type, | 226 | .irq_set_type = sa1100_gpio_type, |
186 | .irq_set_wake = sa1100_high_gpio_wake, | 227 | .irq_set_wake = sa1100_gpio_wake, |
187 | }; | 228 | }; |
188 | 229 | ||
189 | /* | 230 | static int sa1100_high_gpio_irqdomain_map(struct irq_domain *d, |
190 | * We don't need to ACK IRQs on the SA1100 unless they're GPIOs | 231 | unsigned int irq, irq_hw_number_t hwirq) |
191 | * this is for internal IRQs i.e. from 11 to 31. | ||
192 | */ | ||
193 | static void sa1100_mask_irq(struct irq_data *d) | ||
194 | { | ||
195 | ICMR &= ~(1 << d->irq); | ||
196 | } | ||
197 | |||
198 | static void sa1100_unmask_irq(struct irq_data *d) | ||
199 | { | 232 | { |
200 | ICMR |= (1 << d->irq); | 233 | irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip, |
201 | } | 234 | handle_edge_irq); |
235 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
202 | 236 | ||
203 | /* | 237 | return 0; |
204 | * Apart form GPIOs, only the RTC alarm can be a wakeup event. | ||
205 | */ | ||
206 | static int sa1100_set_wake(struct irq_data *d, unsigned int on) | ||
207 | { | ||
208 | if (d->irq == IRQ_RTCAlrm) { | ||
209 | if (on) | ||
210 | PWER |= PWER_RTC; | ||
211 | else | ||
212 | PWER &= ~PWER_RTC; | ||
213 | return 0; | ||
214 | } | ||
215 | return -EINVAL; | ||
216 | } | 238 | } |
217 | 239 | ||
218 | static struct irq_chip sa1100_normal_chip = { | 240 | static struct irq_domain_ops sa1100_high_gpio_irqdomain_ops = { |
219 | .name = "SC", | 241 | .map = sa1100_high_gpio_irqdomain_map, |
220 | .irq_ack = sa1100_mask_irq, | 242 | .xlate = irq_domain_xlate_onetwocell, |
221 | .irq_mask = sa1100_mask_irq, | ||
222 | .irq_unmask = sa1100_unmask_irq, | ||
223 | .irq_set_wake = sa1100_set_wake, | ||
224 | }; | 243 | }; |
225 | 244 | ||
245 | static struct irq_domain *sa1100_high_gpio_irqdomain; | ||
246 | |||
226 | static struct resource irq_resource = | 247 | static struct resource irq_resource = |
227 | DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); | 248 | DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); |
228 | 249 | ||
@@ -291,10 +312,25 @@ static int __init sa1100irq_init_devicefs(void) | |||
291 | 312 | ||
292 | device_initcall(sa1100irq_init_devicefs); | 313 | device_initcall(sa1100irq_init_devicefs); |
293 | 314 | ||
294 | void __init sa1100_init_irq(void) | 315 | static asmlinkage void __exception_irq_entry |
316 | sa1100_handle_irq(struct pt_regs *regs) | ||
295 | { | 317 | { |
296 | unsigned int irq; | 318 | uint32_t icip, icmr, mask; |
319 | |||
320 | do { | ||
321 | icip = (ICIP); | ||
322 | icmr = (ICMR); | ||
323 | mask = icip & icmr; | ||
324 | |||
325 | if (mask == 0) | ||
326 | break; | ||
327 | |||
328 | handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0, regs); | ||
329 | } while (1); | ||
330 | } | ||
297 | 331 | ||
332 | void __init sa1100_init_irq(void) | ||
333 | { | ||
298 | request_resource(&iomem_resource, &irq_resource); | 334 | request_resource(&iomem_resource, &irq_resource); |
299 | 335 | ||
300 | /* disable all IRQs */ | 336 | /* disable all IRQs */ |
@@ -314,29 +350,24 @@ void __init sa1100_init_irq(void) | |||
314 | */ | 350 | */ |
315 | ICCR = 1; | 351 | ICCR = 1; |
316 | 352 | ||
317 | for (irq = 0; irq <= 10; irq++) { | 353 | sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL, |
318 | irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip, | 354 | 11, IRQ_GPIO0, 0, |
319 | handle_edge_irq); | 355 | &sa1100_low_gpio_irqdomain_ops, NULL); |
320 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
321 | } | ||
322 | 356 | ||
323 | for (irq = 12; irq <= 31; irq++) { | 357 | sa1100_normal_irqdomain = irq_domain_add_legacy(NULL, |
324 | irq_set_chip_and_handler(irq, &sa1100_normal_chip, | 358 | 21, IRQ_GPIO11_27, 11, |
325 | handle_level_irq); | 359 | &sa1100_normal_irqdomain_ops, NULL); |
326 | set_irq_flags(irq, IRQF_VALID); | ||
327 | } | ||
328 | 360 | ||
329 | for (irq = 32; irq <= 48; irq++) { | 361 | sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL, |
330 | irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip, | 362 | 17, IRQ_GPIO11, 11, |
331 | handle_edge_irq); | 363 | &sa1100_high_gpio_irqdomain_ops, NULL); |
332 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
333 | } | ||
334 | 364 | ||
335 | /* | 365 | /* |
336 | * Install handler for GPIO 11-27 edge detect interrupts | 366 | * Install handler for GPIO 11-27 edge detect interrupts |
337 | */ | 367 | */ |
338 | irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip); | ||
339 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); | 368 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); |
340 | 369 | ||
370 | set_handle_irq(sa1100_handle_irq); | ||
371 | |||
341 | sa1100_init_gpio(); | 372 | sa1100_init_gpio(); |
342 | } | 373 | } |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ab906b801047..03823e784f63 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -1009,3 +1009,24 @@ config ARCH_SUPPORTS_BIG_ENDIAN | |||
1009 | help | 1009 | help |
1010 | This option specifies the architecture can support big endian | 1010 | This option specifies the architecture can support big endian |
1011 | operation. | 1011 | operation. |
1012 | |||
1013 | config ARM_KERNMEM_PERMS | ||
1014 | bool "Restrict kernel memory permissions" | ||
1015 | help | ||
1016 | If this is set, kernel memory other than kernel text (and rodata) | ||
1017 | will be made non-executable. The tradeoff is that each region is | ||
1018 | padded to section-size (1MiB) boundaries (because their permissions | ||
1019 | are different and splitting the 1M pages into 4K ones causes TLB | ||
1020 | performance problems), wasting memory. | ||
1021 | |||
1022 | config DEBUG_RODATA | ||
1023 | bool "Make kernel text and rodata read-only" | ||
1024 | depends on ARM_KERNMEM_PERMS | ||
1025 | default y | ||
1026 | help | ||
1027 | If this is set, kernel text and rodata will be made read-only. This | ||
1028 | is to help catch accidental or malicious attempts to change the | ||
1029 | kernel's executable code. Additionally splits rodata from kernel | ||
1030 | text so it can be made explicitly non-executable. This creates | ||
1031 | another section-size padded region, so it can waste more memory | ||
1032 | space while gaining the read-only protections. | ||
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 91da64de440f..d3afdf9eb65a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -6,7 +6,7 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ | |||
6 | iomap.o | 6 | iomap.o |
7 | 7 | ||
8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ | 8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ |
9 | mmap.o pgd.o mmu.o | 9 | mmap.o pgd.o mmu.o pageattr.o |
10 | 10 | ||
11 | ifneq ($(CONFIG_MMU),y) | 11 | ifneq ($(CONFIG_MMU),y) |
12 | obj-y += nommu.o | 12 | obj-y += nommu.o |
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 83792f4324ea..2c0c541c60ca 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -113,7 +113,7 @@ static int safe_usermode(int new_usermode, bool warn) | |||
113 | new_usermode |= UM_FIXUP; | 113 | new_usermode |= UM_FIXUP; |
114 | 114 | ||
115 | if (warn) | 115 | if (warn) |
116 | printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n"); | 116 | pr_warn("alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n"); |
117 | } | 117 | } |
118 | 118 | ||
119 | return new_usermode; | 119 | return new_usermode; |
@@ -523,7 +523,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg | |||
523 | * processor for us. | 523 | * processor for us. |
524 | */ | 524 | */ |
525 | if (addr != eaddr) { | 525 | if (addr != eaddr) { |
526 | printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, " | 526 | pr_err("LDMSTM: PC = %08lx, instr = %08lx, " |
527 | "addr = %08lx, eaddr = %08lx\n", | 527 | "addr = %08lx, eaddr = %08lx\n", |
528 | instruction_pointer(regs), instr, addr, eaddr); | 528 | instruction_pointer(regs), instr, addr, eaddr); |
529 | show_regs(regs); | 529 | show_regs(regs); |
@@ -567,7 +567,7 @@ fault: | |||
567 | return TYPE_FAULT; | 567 | return TYPE_FAULT; |
568 | 568 | ||
569 | bad: | 569 | bad: |
570 | printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n"); | 570 | pr_err("Alignment trap: not handling ldm with s-bit set\n"); |
571 | return TYPE_ERROR; | 571 | return TYPE_ERROR; |
572 | } | 572 | } |
573 | 573 | ||
@@ -899,13 +899,13 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
899 | return 0; | 899 | return 0; |
900 | 900 | ||
901 | swp: | 901 | swp: |
902 | printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); | 902 | pr_err("Alignment trap: not handling swp instruction\n"); |
903 | 903 | ||
904 | bad: | 904 | bad: |
905 | /* | 905 | /* |
906 | * Oops, we didn't handle the instruction. | 906 | * Oops, we didn't handle the instruction. |
907 | */ | 907 | */ |
908 | printk(KERN_ERR "Alignment trap: not handling instruction " | 908 | pr_err("Alignment trap: not handling instruction " |
909 | "%0*lx at [<%08lx>]\n", | 909 | "%0*lx at [<%08lx>]\n", |
910 | isize << 1, | 910 | isize << 1, |
911 | isize == 2 ? tinstr : instr, instrptr); | 911 | isize == 2 ? tinstr : instr, instrptr); |
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index e028a7f2ebcc..097181e08c25 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c | |||
@@ -313,7 +313,7 @@ static void __init disable_l2_prefetch(void) | |||
313 | */ | 313 | */ |
314 | u = read_extra_features(); | 314 | u = read_extra_features(); |
315 | if (!(u & 0x01000000)) { | 315 | if (!(u & 0x01000000)) { |
316 | printk(KERN_INFO "Feroceon L2: Disabling L2 prefetch.\n"); | 316 | pr_info("Feroceon L2: Disabling L2 prefetch.\n"); |
317 | write_extra_features(u | 0x01000000); | 317 | write_extra_features(u | 0x01000000); |
318 | } | 318 | } |
319 | } | 319 | } |
@@ -326,7 +326,7 @@ static void __init enable_l2(void) | |||
326 | if (!(u & 0x00400000)) { | 326 | if (!(u & 0x00400000)) { |
327 | int i, d; | 327 | int i, d; |
328 | 328 | ||
329 | printk(KERN_INFO "Feroceon L2: Enabling L2\n"); | 329 | pr_info("Feroceon L2: Enabling L2\n"); |
330 | 330 | ||
331 | d = flush_and_disable_dcache(); | 331 | d = flush_and_disable_dcache(); |
332 | i = invalidate_and_disable_icache(); | 332 | i = invalidate_and_disable_icache(); |
@@ -353,7 +353,7 @@ void __init feroceon_l2_init(int __l2_wt_override) | |||
353 | 353 | ||
354 | enable_l2(); | 354 | enable_l2(); |
355 | 355 | ||
356 | printk(KERN_INFO "Feroceon L2: Cache support initialised%s.\n", | 356 | pr_info("Feroceon L2: Cache support initialised%s.\n", |
357 | l2_wt_override ? ", in WT override mode" : ""); | 357 | l2_wt_override ? ", in WT override mode" : ""); |
358 | } | 358 | } |
359 | #ifdef CONFIG_OF | 359 | #ifdef CONFIG_OF |
diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c index b273739e6359..1e373d268c04 100644 --- a/arch/arm/mm/cache-tauros2.c +++ b/arch/arm/mm/cache-tauros2.c | |||
@@ -185,7 +185,7 @@ static void enable_extra_feature(unsigned int features) | |||
185 | u &= ~0x01000000; | 185 | u &= ~0x01000000; |
186 | else | 186 | else |
187 | u |= 0x01000000; | 187 | u |= 0x01000000; |
188 | printk(KERN_INFO "Tauros2: %s L2 prefetch.\n", | 188 | pr_info("Tauros2: %s L2 prefetch.\n", |
189 | (features & CACHE_TAUROS2_PREFETCH_ON) | 189 | (features & CACHE_TAUROS2_PREFETCH_ON) |
190 | ? "Enabling" : "Disabling"); | 190 | ? "Enabling" : "Disabling"); |
191 | 191 | ||
@@ -193,7 +193,7 @@ static void enable_extra_feature(unsigned int features) | |||
193 | u |= 0x00100000; | 193 | u |= 0x00100000; |
194 | else | 194 | else |
195 | u &= ~0x00100000; | 195 | u &= ~0x00100000; |
196 | printk(KERN_INFO "Tauros2: %s line fill burt8.\n", | 196 | pr_info("Tauros2: %s line fill burt8.\n", |
197 | (features & CACHE_TAUROS2_LINEFILL_BURST8) | 197 | (features & CACHE_TAUROS2_LINEFILL_BURST8) |
198 | ? "Enabling" : "Disabling"); | 198 | ? "Enabling" : "Disabling"); |
199 | 199 | ||
@@ -216,7 +216,7 @@ static void __init tauros2_internal_init(unsigned int features) | |||
216 | */ | 216 | */ |
217 | feat = read_extra_features(); | 217 | feat = read_extra_features(); |
218 | if (!(feat & 0x00400000)) { | 218 | if (!(feat & 0x00400000)) { |
219 | printk(KERN_INFO "Tauros2: Enabling L2 cache.\n"); | 219 | pr_info("Tauros2: Enabling L2 cache.\n"); |
220 | write_extra_features(feat | 0x00400000); | 220 | write_extra_features(feat | 0x00400000); |
221 | } | 221 | } |
222 | 222 | ||
@@ -253,7 +253,7 @@ static void __init tauros2_internal_init(unsigned int features) | |||
253 | */ | 253 | */ |
254 | actlr = read_actlr(); | 254 | actlr = read_actlr(); |
255 | if (!(actlr & 0x00000002)) { | 255 | if (!(actlr & 0x00000002)) { |
256 | printk(KERN_INFO "Tauros2: Enabling L2 cache.\n"); | 256 | pr_info("Tauros2: Enabling L2 cache.\n"); |
257 | write_actlr(actlr | 0x00000002); | 257 | write_actlr(actlr | 0x00000002); |
258 | } | 258 | } |
259 | 259 | ||
@@ -262,11 +262,11 @@ static void __init tauros2_internal_init(unsigned int features) | |||
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | if (mode == NULL) { | 264 | if (mode == NULL) { |
265 | printk(KERN_CRIT "Tauros2: Unable to detect CPU mode.\n"); | 265 | pr_crit("Tauros2: Unable to detect CPU mode.\n"); |
266 | return; | 266 | return; |
267 | } | 267 | } |
268 | 268 | ||
269 | printk(KERN_INFO "Tauros2: L2 cache support initialised " | 269 | pr_info("Tauros2: L2 cache support initialised " |
270 | "in %s mode.\n", mode); | 270 | "in %s mode.\n", mode); |
271 | } | 271 | } |
272 | 272 | ||
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 6eb97b3a7481..91892569710f 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -184,36 +184,46 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
184 | u64 asid = atomic64_read(&mm->context.id); | 184 | u64 asid = atomic64_read(&mm->context.id); |
185 | u64 generation = atomic64_read(&asid_generation); | 185 | u64 generation = atomic64_read(&asid_generation); |
186 | 186 | ||
187 | if (asid != 0 && is_reserved_asid(asid)) { | 187 | if (asid != 0) { |
188 | /* | 188 | /* |
189 | * Our current ASID was active during a rollover, we can | 189 | * If our current ASID was active during a rollover, we |
190 | * continue to use it and this was just a false alarm. | 190 | * can continue to use it and this was just a false alarm. |
191 | */ | 191 | */ |
192 | asid = generation | (asid & ~ASID_MASK); | 192 | if (is_reserved_asid(asid)) |
193 | } else { | 193 | return generation | (asid & ~ASID_MASK); |
194 | |||
194 | /* | 195 | /* |
195 | * Allocate a free ASID. If we can't find one, take a | 196 | * We had a valid ASID in a previous life, so try to re-use |
196 | * note of the currently active ASIDs and mark the TLBs | 197 | * it if possible., |
197 | * as requiring flushes. We always count from ASID #1, | ||
198 | * as we reserve ASID #0 to switch via TTBR0 and to | ||
199 | * avoid speculative page table walks from hitting in | ||
200 | * any partial walk caches, which could be populated | ||
201 | * from overlapping level-1 descriptors used to map both | ||
202 | * the module area and the userspace stack. | ||
203 | */ | 198 | */ |
204 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); | 199 | asid &= ~ASID_MASK; |
205 | if (asid == NUM_USER_ASIDS) { | 200 | if (!__test_and_set_bit(asid, asid_map)) |
206 | generation = atomic64_add_return(ASID_FIRST_VERSION, | 201 | goto bump_gen; |
207 | &asid_generation); | ||
208 | flush_context(cpu); | ||
209 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); | ||
210 | } | ||
211 | __set_bit(asid, asid_map); | ||
212 | cur_idx = asid; | ||
213 | asid |= generation; | ||
214 | cpumask_clear(mm_cpumask(mm)); | ||
215 | } | 202 | } |
216 | 203 | ||
204 | /* | ||
205 | * Allocate a free ASID. If we can't find one, take a note of the | ||
206 | * currently active ASIDs and mark the TLBs as requiring flushes. | ||
207 | * We always count from ASID #1, as we reserve ASID #0 to switch | ||
208 | * via TTBR0 and to avoid speculative page table walks from hitting | ||
209 | * in any partial walk caches, which could be populated from | ||
210 | * overlapping level-1 descriptors used to map both the module | ||
211 | * area and the userspace stack. | ||
212 | */ | ||
213 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); | ||
214 | if (asid == NUM_USER_ASIDS) { | ||
215 | generation = atomic64_add_return(ASID_FIRST_VERSION, | ||
216 | &asid_generation); | ||
217 | flush_context(cpu); | ||
218 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); | ||
219 | } | ||
220 | |||
221 | __set_bit(asid, asid_map); | ||
222 | cur_idx = asid; | ||
223 | |||
224 | bump_gen: | ||
225 | asid |= generation; | ||
226 | cpumask_clear(mm_cpumask(mm)); | ||
217 | return asid; | 227 | return asid; |
218 | } | 228 | } |
219 | 229 | ||
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index b9bcc9d79176..70423345da26 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c | |||
@@ -62,7 +62,7 @@ static void discard_old_kernel_data(void *kto) | |||
62 | __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" | 62 | __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" |
63 | : | 63 | : |
64 | : "r" (kto), | 64 | : "r" (kto), |
65 | "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES) | 65 | "r" ((unsigned long)kto + PAGE_SIZE - 1) |
66 | : "cc"); | 66 | : "cc"); |
67 | } | 67 | } |
68 | 68 | ||
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index ff379ac115df..d9e0d00a6699 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -235,7 +235,7 @@ void __init check_writebuffer_bugs(void) | |||
235 | const char *reason; | 235 | const char *reason; |
236 | unsigned long v = 1; | 236 | unsigned long v = 1; |
237 | 237 | ||
238 | printk(KERN_INFO "CPU: Testing write buffer coherency: "); | 238 | pr_info("CPU: Testing write buffer coherency: "); |
239 | 239 | ||
240 | page = alloc_page(GFP_KERNEL); | 240 | page = alloc_page(GFP_KERNEL); |
241 | if (page) { | 241 | if (page) { |
@@ -261,9 +261,9 @@ void __init check_writebuffer_bugs(void) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | if (v) { | 263 | if (v) { |
264 | printk("failed, %s\n", reason); | 264 | pr_cont("failed, %s\n", reason); |
265 | shared_pte_mask = L_PTE_MT_UNCACHED; | 265 | shared_pte_mask = L_PTE_MT_UNCACHED; |
266 | } else { | 266 | } else { |
267 | printk("ok\n"); | 267 | pr_cont("ok\n"); |
268 | } | 268 | } |
269 | } | 269 | } |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index eb8830a4c5ed..a982dc3190df 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -63,9 +63,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
63 | if (!mm) | 63 | if (!mm) |
64 | mm = &init_mm; | 64 | mm = &init_mm; |
65 | 65 | ||
66 | printk(KERN_ALERT "pgd = %p\n", mm->pgd); | 66 | pr_alert("pgd = %p\n", mm->pgd); |
67 | pgd = pgd_offset(mm, addr); | 67 | pgd = pgd_offset(mm, addr); |
68 | printk(KERN_ALERT "[%08lx] *pgd=%08llx", | 68 | pr_alert("[%08lx] *pgd=%08llx", |
69 | addr, (long long)pgd_val(*pgd)); | 69 | addr, (long long)pgd_val(*pgd)); |
70 | 70 | ||
71 | do { | 71 | do { |
@@ -77,31 +77,31 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
77 | break; | 77 | break; |
78 | 78 | ||
79 | if (pgd_bad(*pgd)) { | 79 | if (pgd_bad(*pgd)) { |
80 | printk("(bad)"); | 80 | pr_cont("(bad)"); |
81 | break; | 81 | break; |
82 | } | 82 | } |
83 | 83 | ||
84 | pud = pud_offset(pgd, addr); | 84 | pud = pud_offset(pgd, addr); |
85 | if (PTRS_PER_PUD != 1) | 85 | if (PTRS_PER_PUD != 1) |
86 | printk(", *pud=%08llx", (long long)pud_val(*pud)); | 86 | pr_cont(", *pud=%08llx", (long long)pud_val(*pud)); |
87 | 87 | ||
88 | if (pud_none(*pud)) | 88 | if (pud_none(*pud)) |
89 | break; | 89 | break; |
90 | 90 | ||
91 | if (pud_bad(*pud)) { | 91 | if (pud_bad(*pud)) { |
92 | printk("(bad)"); | 92 | pr_cont("(bad)"); |
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | 95 | ||
96 | pmd = pmd_offset(pud, addr); | 96 | pmd = pmd_offset(pud, addr); |
97 | if (PTRS_PER_PMD != 1) | 97 | if (PTRS_PER_PMD != 1) |
98 | printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); | 98 | pr_cont(", *pmd=%08llx", (long long)pmd_val(*pmd)); |
99 | 99 | ||
100 | if (pmd_none(*pmd)) | 100 | if (pmd_none(*pmd)) |
101 | break; | 101 | break; |
102 | 102 | ||
103 | if (pmd_bad(*pmd)) { | 103 | if (pmd_bad(*pmd)) { |
104 | printk("(bad)"); | 104 | pr_cont("(bad)"); |
105 | break; | 105 | break; |
106 | } | 106 | } |
107 | 107 | ||
@@ -110,15 +110,15 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
110 | break; | 110 | break; |
111 | 111 | ||
112 | pte = pte_offset_map(pmd, addr); | 112 | pte = pte_offset_map(pmd, addr); |
113 | printk(", *pte=%08llx", (long long)pte_val(*pte)); | 113 | pr_cont(", *pte=%08llx", (long long)pte_val(*pte)); |
114 | #ifndef CONFIG_ARM_LPAE | 114 | #ifndef CONFIG_ARM_LPAE |
115 | printk(", *ppte=%08llx", | 115 | pr_cont(", *ppte=%08llx", |
116 | (long long)pte_val(pte[PTE_HWTABLE_PTRS])); | 116 | (long long)pte_val(pte[PTE_HWTABLE_PTRS])); |
117 | #endif | 117 | #endif |
118 | pte_unmap(pte); | 118 | pte_unmap(pte); |
119 | } while(0); | 119 | } while(0); |
120 | 120 | ||
121 | printk("\n"); | 121 | pr_cont("\n"); |
122 | } | 122 | } |
123 | #else /* CONFIG_MMU */ | 123 | #else /* CONFIG_MMU */ |
124 | void show_pte(struct mm_struct *mm, unsigned long addr) | 124 | void show_pte(struct mm_struct *mm, unsigned long addr) |
@@ -142,10 +142,9 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, | |||
142 | * No handler, we'll have to terminate things with extreme prejudice. | 142 | * No handler, we'll have to terminate things with extreme prejudice. |
143 | */ | 143 | */ |
144 | bust_spinlocks(1); | 144 | bust_spinlocks(1); |
145 | printk(KERN_ALERT | 145 | pr_alert("Unable to handle kernel %s at virtual address %08lx\n", |
146 | "Unable to handle kernel %s at virtual address %08lx\n", | 146 | (addr < PAGE_SIZE) ? "NULL pointer dereference" : |
147 | (addr < PAGE_SIZE) ? "NULL pointer dereference" : | 147 | "paging request", addr); |
148 | "paging request", addr); | ||
149 | 148 | ||
150 | show_pte(mm, addr); | 149 | show_pte(mm, addr); |
151 | die("Oops", regs, fsr); | 150 | die("Oops", regs, fsr); |
@@ -551,7 +550,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
551 | if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) | 550 | if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) |
552 | return; | 551 | return; |
553 | 552 | ||
554 | printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", | 553 | pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", |
555 | inf->name, fsr, addr); | 554 | inf->name, fsr, addr); |
556 | 555 | ||
557 | info.si_signo = inf->sig; | 556 | info.si_signo = inf->sig; |
@@ -583,7 +582,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) | |||
583 | if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) | 582 | if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) |
584 | return; | 583 | return; |
585 | 584 | ||
586 | printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", | 585 | pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", |
587 | inf->name, ifsr, addr); | 586 | inf->name, ifsr, addr); |
588 | 587 | ||
589 | info.si_signo = inf->sig; | 588 | info.si_signo = inf->sig; |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 265b836b3bd1..34b66af516ea 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -33,7 +33,7 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) | |||
33 | asm( "mcrr p15, 0, %1, %0, c14\n" | 33 | asm( "mcrr p15, 0, %1, %0, c14\n" |
34 | " mcr p15, 0, %2, c7, c10, 4" | 34 | " mcr p15, 0, %2, c7, c10, 4" |
35 | : | 35 | : |
36 | : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero) | 36 | : "r" (to), "r" (to + PAGE_SIZE - 1), "r" (zero) |
37 | : "cc"); | 37 | : "cc"); |
38 | } | 38 | } |
39 | 39 | ||
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index e17ed00828d7..b98895d9fe57 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
@@ -18,19 +18,20 @@ | |||
18 | #include <asm/tlbflush.h> | 18 | #include <asm/tlbflush.h> |
19 | #include "mm.h" | 19 | #include "mm.h" |
20 | 20 | ||
21 | pte_t *fixmap_page_table; | ||
22 | |||
23 | static inline void set_fixmap_pte(int idx, pte_t pte) | 21 | static inline void set_fixmap_pte(int idx, pte_t pte) |
24 | { | 22 | { |
25 | unsigned long vaddr = __fix_to_virt(idx); | 23 | unsigned long vaddr = __fix_to_virt(idx); |
26 | set_pte_ext(fixmap_page_table + idx, pte, 0); | 24 | pte_t *ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
25 | |||
26 | set_pte_ext(ptep, pte, 0); | ||
27 | local_flush_tlb_kernel_page(vaddr); | 27 | local_flush_tlb_kernel_page(vaddr); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline pte_t get_fixmap_pte(unsigned long vaddr) | 30 | static inline pte_t get_fixmap_pte(unsigned long vaddr) |
31 | { | 31 | { |
32 | unsigned long idx = __virt_to_fix(vaddr); | 32 | pte_t *ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
33 | return *(fixmap_page_table + idx); | 33 | |
34 | return *ptep; | ||
34 | } | 35 | } |
35 | 36 | ||
36 | void *kmap(struct page *page) | 37 | void *kmap(struct page *page) |
@@ -84,7 +85,7 @@ void *kmap_atomic(struct page *page) | |||
84 | * With debugging enabled, kunmap_atomic forces that entry to 0. | 85 | * With debugging enabled, kunmap_atomic forces that entry to 0. |
85 | * Make sure it was indeed properly unmapped. | 86 | * Make sure it was indeed properly unmapped. |
86 | */ | 87 | */ |
87 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); | 88 | BUG_ON(!pte_none(get_fixmap_pte(vaddr))); |
88 | #endif | 89 | #endif |
89 | /* | 90 | /* |
90 | * When debugging is off, kunmap_atomic leaves the previous mapping | 91 | * When debugging is off, kunmap_atomic leaves the previous mapping |
@@ -137,7 +138,7 @@ void *kmap_atomic_pfn(unsigned long pfn) | |||
137 | idx = type + KM_TYPE_NR * smp_processor_id(); | 138 | idx = type + KM_TYPE_NR * smp_processor_id(); |
138 | vaddr = __fix_to_virt(idx); | 139 | vaddr = __fix_to_virt(idx); |
139 | #ifdef CONFIG_DEBUG_HIGHMEM | 140 | #ifdef CONFIG_DEBUG_HIGHMEM |
140 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); | 141 | BUG_ON(!pte_none(get_fixmap_pte(vaddr))); |
141 | #endif | 142 | #endif |
142 | set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); | 143 | set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); |
143 | 144 | ||
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9481f85c56e6..98ad9c79ea0e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
31 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
32 | #include <asm/system_info.h> | ||
32 | #include <asm/tlb.h> | 33 | #include <asm/tlb.h> |
33 | #include <asm/fixmap.h> | 34 | #include <asm/fixmap.h> |
34 | 35 | ||
@@ -67,7 +68,7 @@ early_param("initrd", early_initrd); | |||
67 | 68 | ||
68 | static int __init parse_tag_initrd(const struct tag *tag) | 69 | static int __init parse_tag_initrd(const struct tag *tag) |
69 | { | 70 | { |
70 | printk(KERN_WARNING "ATAG_INITRD is deprecated; " | 71 | pr_warn("ATAG_INITRD is deprecated; " |
71 | "please update your bootloader.\n"); | 72 | "please update your bootloader.\n"); |
72 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); | 73 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); |
73 | phys_initrd_size = tag->u.initrd.size; | 74 | phys_initrd_size = tag->u.initrd.size; |
@@ -544,7 +545,7 @@ void __init mem_init(void) | |||
544 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 | 545 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 |
545 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) | 546 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) |
546 | 547 | ||
547 | printk(KERN_NOTICE "Virtual kernel memory layout:\n" | 548 | pr_notice("Virtual kernel memory layout:\n" |
548 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" | 549 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" |
549 | #ifdef CONFIG_HAVE_TCM | 550 | #ifdef CONFIG_HAVE_TCM |
550 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" | 551 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" |
@@ -570,7 +571,7 @@ void __init mem_init(void) | |||
570 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), | 571 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), |
571 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), | 572 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), |
572 | #endif | 573 | #endif |
573 | MLK(FIXADDR_START, FIXADDR_TOP), | 574 | MLK(FIXADDR_START, FIXADDR_END), |
574 | MLM(VMALLOC_START, VMALLOC_END), | 575 | MLM(VMALLOC_START, VMALLOC_END), |
575 | MLM(PAGE_OFFSET, (unsigned long)high_memory), | 576 | MLM(PAGE_OFFSET, (unsigned long)high_memory), |
576 | #ifdef CONFIG_HIGHMEM | 577 | #ifdef CONFIG_HIGHMEM |
@@ -615,7 +616,145 @@ void __init mem_init(void) | |||
615 | } | 616 | } |
616 | } | 617 | } |
617 | 618 | ||
618 | void free_initmem(void) | 619 | #ifdef CONFIG_ARM_KERNMEM_PERMS |
620 | struct section_perm { | ||
621 | unsigned long start; | ||
622 | unsigned long end; | ||
623 | pmdval_t mask; | ||
624 | pmdval_t prot; | ||
625 | pmdval_t clear; | ||
626 | }; | ||
627 | |||
628 | static struct section_perm nx_perms[] = { | ||
629 | /* Make pages tables, etc before _stext RW (set NX). */ | ||
630 | { | ||
631 | .start = PAGE_OFFSET, | ||
632 | .end = (unsigned long)_stext, | ||
633 | .mask = ~PMD_SECT_XN, | ||
634 | .prot = PMD_SECT_XN, | ||
635 | }, | ||
636 | /* Make init RW (set NX). */ | ||
637 | { | ||
638 | .start = (unsigned long)__init_begin, | ||
639 | .end = (unsigned long)_sdata, | ||
640 | .mask = ~PMD_SECT_XN, | ||
641 | .prot = PMD_SECT_XN, | ||
642 | }, | ||
643 | #ifdef CONFIG_DEBUG_RODATA | ||
644 | /* Make rodata NX (set RO in ro_perms below). */ | ||
645 | { | ||
646 | .start = (unsigned long)__start_rodata, | ||
647 | .end = (unsigned long)__init_begin, | ||
648 | .mask = ~PMD_SECT_XN, | ||
649 | .prot = PMD_SECT_XN, | ||
650 | }, | ||
651 | #endif | ||
652 | }; | ||
653 | |||
654 | #ifdef CONFIG_DEBUG_RODATA | ||
655 | static struct section_perm ro_perms[] = { | ||
656 | /* Make kernel code and rodata RX (set RO). */ | ||
657 | { | ||
658 | .start = (unsigned long)_stext, | ||
659 | .end = (unsigned long)__init_begin, | ||
660 | #ifdef CONFIG_ARM_LPAE | ||
661 | .mask = ~PMD_SECT_RDONLY, | ||
662 | .prot = PMD_SECT_RDONLY, | ||
663 | #else | ||
664 | .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), | ||
665 | .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, | ||
666 | .clear = PMD_SECT_AP_WRITE, | ||
667 | #endif | ||
668 | }, | ||
669 | }; | ||
670 | #endif | ||
671 | |||
672 | /* | ||
673 | * Updates section permissions only for the current mm (sections are | ||
674 | * copied into each mm). During startup, this is the init_mm. Is only | ||
675 | * safe to be called with preemption disabled, as under stop_machine(). | ||
676 | */ | ||
677 | static inline void section_update(unsigned long addr, pmdval_t mask, | ||
678 | pmdval_t prot) | ||
679 | { | ||
680 | struct mm_struct *mm; | ||
681 | pmd_t *pmd; | ||
682 | |||
683 | mm = current->active_mm; | ||
684 | pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); | ||
685 | |||
686 | #ifdef CONFIG_ARM_LPAE | ||
687 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
688 | #else | ||
689 | if (addr & SECTION_SIZE) | ||
690 | pmd[1] = __pmd((pmd_val(pmd[1]) & mask) | prot); | ||
691 | else | ||
692 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
693 | #endif | ||
694 | flush_pmd_entry(pmd); | ||
695 | local_flush_tlb_kernel_range(addr, addr + SECTION_SIZE); | ||
696 | } | ||
697 | |||
698 | /* Make sure extended page tables are in use. */ | ||
699 | static inline bool arch_has_strict_perms(void) | ||
700 | { | ||
701 | if (cpu_architecture() < CPU_ARCH_ARMv6) | ||
702 | return false; | ||
703 | |||
704 | return !!(get_cr() & CR_XP); | ||
705 | } | ||
706 | |||
707 | #define set_section_perms(perms, field) { \ | ||
708 | size_t i; \ | ||
709 | unsigned long addr; \ | ||
710 | \ | ||
711 | if (!arch_has_strict_perms()) \ | ||
712 | return; \ | ||
713 | \ | ||
714 | for (i = 0; i < ARRAY_SIZE(perms); i++) { \ | ||
715 | if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) || \ | ||
716 | !IS_ALIGNED(perms[i].end, SECTION_SIZE)) { \ | ||
717 | pr_err("BUG: section %lx-%lx not aligned to %lx\n", \ | ||
718 | perms[i].start, perms[i].end, \ | ||
719 | SECTION_SIZE); \ | ||
720 | continue; \ | ||
721 | } \ | ||
722 | \ | ||
723 | for (addr = perms[i].start; \ | ||
724 | addr < perms[i].end; \ | ||
725 | addr += SECTION_SIZE) \ | ||
726 | section_update(addr, perms[i].mask, \ | ||
727 | perms[i].field); \ | ||
728 | } \ | ||
729 | } | ||
730 | |||
731 | static inline void fix_kernmem_perms(void) | ||
732 | { | ||
733 | set_section_perms(nx_perms, prot); | ||
734 | } | ||
735 | |||
736 | #ifdef CONFIG_DEBUG_RODATA | ||
737 | void mark_rodata_ro(void) | ||
738 | { | ||
739 | set_section_perms(ro_perms, prot); | ||
740 | } | ||
741 | |||
742 | void set_kernel_text_rw(void) | ||
743 | { | ||
744 | set_section_perms(ro_perms, clear); | ||
745 | } | ||
746 | |||
747 | void set_kernel_text_ro(void) | ||
748 | { | ||
749 | set_section_perms(ro_perms, prot); | ||
750 | } | ||
751 | #endif /* CONFIG_DEBUG_RODATA */ | ||
752 | |||
753 | #else | ||
754 | static inline void fix_kernmem_perms(void) { } | ||
755 | #endif /* CONFIG_ARM_KERNMEM_PERMS */ | ||
756 | |||
757 | void free_tcmmem(void) | ||
619 | { | 758 | { |
620 | #ifdef CONFIG_HAVE_TCM | 759 | #ifdef CONFIG_HAVE_TCM |
621 | extern char __tcm_start, __tcm_end; | 760 | extern char __tcm_start, __tcm_end; |
@@ -623,6 +762,12 @@ void free_initmem(void) | |||
623 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); | 762 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); |
624 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); | 763 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); |
625 | #endif | 764 | #endif |
765 | } | ||
766 | |||
767 | void free_initmem(void) | ||
768 | { | ||
769 | fix_kernmem_perms(); | ||
770 | free_tcmmem(); | ||
626 | 771 | ||
627 | poison_init_mem(__init_begin, __init_end - __init_begin); | 772 | poison_init_mem(__init_begin, __init_end - __init_begin); |
628 | if (!machine_is_integrator() && !machine_is_cintegrator()) | 773 | if (!machine_is_integrator() && !machine_is_cintegrator()) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9f98cec7fe1e..cda7c40999b6 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/cputype.h> | 22 | #include <asm/cputype.h> |
23 | #include <asm/sections.h> | 23 | #include <asm/sections.h> |
24 | #include <asm/cachetype.h> | 24 | #include <asm/cachetype.h> |
25 | #include <asm/fixmap.h> | ||
25 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
27 | #include <asm/smp_plat.h> | 28 | #include <asm/smp_plat.h> |
@@ -52,6 +53,8 @@ EXPORT_SYMBOL(empty_zero_page); | |||
52 | */ | 53 | */ |
53 | pmd_t *top_pmd; | 54 | pmd_t *top_pmd; |
54 | 55 | ||
56 | pmdval_t user_pmd_table = _PAGE_USER_TABLE; | ||
57 | |||
55 | #define CPOLICY_UNCACHED 0 | 58 | #define CPOLICY_UNCACHED 0 |
56 | #define CPOLICY_BUFFERED 1 | 59 | #define CPOLICY_BUFFERED 1 |
57 | #define CPOLICY_WRITETHROUGH 2 | 60 | #define CPOLICY_WRITETHROUGH 2 |
@@ -192,7 +195,7 @@ early_param("cachepolicy", early_cachepolicy); | |||
192 | static int __init early_nocache(char *__unused) | 195 | static int __init early_nocache(char *__unused) |
193 | { | 196 | { |
194 | char *p = "buffered"; | 197 | char *p = "buffered"; |
195 | printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p); | 198 | pr_warn("nocache is deprecated; use cachepolicy=%s\n", p); |
196 | early_cachepolicy(p); | 199 | early_cachepolicy(p); |
197 | return 0; | 200 | return 0; |
198 | } | 201 | } |
@@ -201,7 +204,7 @@ early_param("nocache", early_nocache); | |||
201 | static int __init early_nowrite(char *__unused) | 204 | static int __init early_nowrite(char *__unused) |
202 | { | 205 | { |
203 | char *p = "uncached"; | 206 | char *p = "uncached"; |
204 | printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p); | 207 | pr_warn("nowb is deprecated; use cachepolicy=%s\n", p); |
205 | early_cachepolicy(p); | 208 | early_cachepolicy(p); |
206 | return 0; | 209 | return 0; |
207 | } | 210 | } |
@@ -354,43 +357,28 @@ const struct mem_type *get_mem_type(unsigned int type) | |||
354 | } | 357 | } |
355 | EXPORT_SYMBOL(get_mem_type); | 358 | EXPORT_SYMBOL(get_mem_type); |
356 | 359 | ||
357 | #define PTE_SET_FN(_name, pteop) \ | 360 | /* |
358 | static int pte_set_##_name(pte_t *ptep, pgtable_t token, unsigned long addr, \ | 361 | * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range(). |
359 | void *data) \ | 362 | * As a result, this can only be called with preemption disabled, as under |
360 | { \ | 363 | * stop_machine(). |
361 | pte_t pte = pteop(*ptep); \ | 364 | */ |
362 | \ | 365 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) |
363 | set_pte_ext(ptep, pte, 0); \ | 366 | { |
364 | return 0; \ | 367 | unsigned long vaddr = __fix_to_virt(idx); |
365 | } \ | 368 | pte_t *pte = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
366 | |||
367 | #define SET_MEMORY_FN(_name, callback) \ | ||
368 | int set_memory_##_name(unsigned long addr, int numpages) \ | ||
369 | { \ | ||
370 | unsigned long start = addr; \ | ||
371 | unsigned long size = PAGE_SIZE*numpages; \ | ||
372 | unsigned end = start + size; \ | ||
373 | \ | ||
374 | if (start < MODULES_VADDR || start >= MODULES_END) \ | ||
375 | return -EINVAL;\ | ||
376 | \ | ||
377 | if (end < MODULES_VADDR || end >= MODULES_END) \ | ||
378 | return -EINVAL; \ | ||
379 | \ | ||
380 | apply_to_page_range(&init_mm, start, size, callback, NULL); \ | ||
381 | flush_tlb_kernel_range(start, end); \ | ||
382 | return 0;\ | ||
383 | } | ||
384 | 369 | ||
385 | PTE_SET_FN(ro, pte_wrprotect) | 370 | /* Make sure fixmap region does not exceed available allocation. */ |
386 | PTE_SET_FN(rw, pte_mkwrite) | 371 | BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) > |
387 | PTE_SET_FN(x, pte_mkexec) | 372 | FIXADDR_END); |
388 | PTE_SET_FN(nx, pte_mknexec) | 373 | BUG_ON(idx >= __end_of_fixed_addresses); |
389 | 374 | ||
390 | SET_MEMORY_FN(ro, pte_set_ro) | 375 | if (pgprot_val(prot)) |
391 | SET_MEMORY_FN(rw, pte_set_rw) | 376 | set_pte_at(NULL, vaddr, pte, |
392 | SET_MEMORY_FN(x, pte_set_x) | 377 | pfn_pte(phys >> PAGE_SHIFT, prot)); |
393 | SET_MEMORY_FN(nx, pte_set_nx) | 378 | else |
379 | pte_clear(NULL, vaddr, pte); | ||
380 | local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); | ||
381 | } | ||
394 | 382 | ||
395 | /* | 383 | /* |
396 | * Adjust the PMD section entries according to the CPU in use. | 384 | * Adjust the PMD section entries according to the CPU in use. |
@@ -528,14 +516,23 @@ static void __init build_mem_type_table(void) | |||
528 | hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; | 516 | hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; |
529 | s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; | 517 | s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; |
530 | 518 | ||
519 | #ifndef CONFIG_ARM_LPAE | ||
531 | /* | 520 | /* |
532 | * We don't use domains on ARMv6 (since this causes problems with | 521 | * We don't use domains on ARMv6 (since this causes problems with |
533 | * v6/v7 kernels), so we must use a separate memory type for user | 522 | * v6/v7 kernels), so we must use a separate memory type for user |
534 | * r/o, kernel r/w to map the vectors page. | 523 | * r/o, kernel r/w to map the vectors page. |
535 | */ | 524 | */ |
536 | #ifndef CONFIG_ARM_LPAE | ||
537 | if (cpu_arch == CPU_ARCH_ARMv6) | 525 | if (cpu_arch == CPU_ARCH_ARMv6) |
538 | vecs_pgprot |= L_PTE_MT_VECTORS; | 526 | vecs_pgprot |= L_PTE_MT_VECTORS; |
527 | |||
528 | /* | ||
529 | * Check is it with support for the PXN bit | ||
530 | * in the Short-descriptor translation table format descriptors. | ||
531 | */ | ||
532 | if (cpu_arch == CPU_ARCH_ARMv7 && | ||
533 | (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) == 4) { | ||
534 | user_pmd_table |= PMD_PXNTABLE; | ||
535 | } | ||
539 | #endif | 536 | #endif |
540 | 537 | ||
541 | /* | 538 | /* |
@@ -605,6 +602,11 @@ static void __init build_mem_type_table(void) | |||
605 | } | 602 | } |
606 | kern_pgprot |= PTE_EXT_AF; | 603 | kern_pgprot |= PTE_EXT_AF; |
607 | vecs_pgprot |= PTE_EXT_AF; | 604 | vecs_pgprot |= PTE_EXT_AF; |
605 | |||
606 | /* | ||
607 | * Set PXN for user mappings | ||
608 | */ | ||
609 | user_pgprot |= PTE_EXT_PXN; | ||
608 | #endif | 610 | #endif |
609 | 611 | ||
610 | for (i = 0; i < 16; i++) { | 612 | for (i = 0; i < 16; i++) { |
@@ -786,8 +788,7 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
786 | length = PAGE_ALIGN(md->length); | 788 | length = PAGE_ALIGN(md->length); |
787 | 789 | ||
788 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { | 790 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { |
789 | printk(KERN_ERR "MM: CPU does not support supersection " | 791 | pr_err("MM: CPU does not support supersection mapping for 0x%08llx at 0x%08lx\n", |
790 | "mapping for 0x%08llx at 0x%08lx\n", | ||
791 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 792 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
792 | return; | 793 | return; |
793 | } | 794 | } |
@@ -799,15 +800,13 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
799 | * of the actual domain assignments in use. | 800 | * of the actual domain assignments in use. |
800 | */ | 801 | */ |
801 | if (type->domain) { | 802 | if (type->domain) { |
802 | printk(KERN_ERR "MM: invalid domain in supersection " | 803 | pr_err("MM: invalid domain in supersection mapping for 0x%08llx at 0x%08lx\n", |
803 | "mapping for 0x%08llx at 0x%08lx\n", | ||
804 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 804 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
805 | return; | 805 | return; |
806 | } | 806 | } |
807 | 807 | ||
808 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { | 808 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { |
809 | printk(KERN_ERR "MM: cannot create mapping for 0x%08llx" | 809 | pr_err("MM: cannot create mapping for 0x%08llx at 0x%08lx invalid alignment\n", |
810 | " at 0x%08lx invalid alignment\n", | ||
811 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 810 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
812 | return; | 811 | return; |
813 | } | 812 | } |
@@ -850,18 +849,16 @@ static void __init create_mapping(struct map_desc *md) | |||
850 | pgd_t *pgd; | 849 | pgd_t *pgd; |
851 | 850 | ||
852 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { | 851 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { |
853 | printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx" | 852 | pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", |
854 | " at 0x%08lx in user region\n", | 853 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
855 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); | ||
856 | return; | 854 | return; |
857 | } | 855 | } |
858 | 856 | ||
859 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && | 857 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && |
860 | md->virtual >= PAGE_OFFSET && | 858 | md->virtual >= PAGE_OFFSET && |
861 | (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { | 859 | (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { |
862 | printk(KERN_WARNING "BUG: mapping for 0x%08llx" | 860 | pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", |
863 | " at 0x%08lx out of vmalloc space\n", | 861 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
864 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); | ||
865 | } | 862 | } |
866 | 863 | ||
867 | type = &mem_types[md->type]; | 864 | type = &mem_types[md->type]; |
@@ -881,9 +878,8 @@ static void __init create_mapping(struct map_desc *md) | |||
881 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); | 878 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); |
882 | 879 | ||
883 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { | 880 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { |
884 | printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not " | 881 | pr_warn("BUG: map for 0x%08llx at 0x%08lx can not be mapped using pages, ignoring.\n", |
885 | "be mapped using pages, ignoring.\n", | 882 | (long long)__pfn_to_phys(md->pfn), addr); |
886 | (long long)__pfn_to_phys(md->pfn), addr); | ||
887 | return; | 883 | return; |
888 | } | 884 | } |
889 | 885 | ||
@@ -1053,15 +1049,13 @@ static int __init early_vmalloc(char *arg) | |||
1053 | 1049 | ||
1054 | if (vmalloc_reserve < SZ_16M) { | 1050 | if (vmalloc_reserve < SZ_16M) { |
1055 | vmalloc_reserve = SZ_16M; | 1051 | vmalloc_reserve = SZ_16M; |
1056 | printk(KERN_WARNING | 1052 | pr_warn("vmalloc area too small, limiting to %luMB\n", |
1057 | "vmalloc area too small, limiting to %luMB\n", | ||
1058 | vmalloc_reserve >> 20); | 1053 | vmalloc_reserve >> 20); |
1059 | } | 1054 | } |
1060 | 1055 | ||
1061 | if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { | 1056 | if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { |
1062 | vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); | 1057 | vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); |
1063 | printk(KERN_WARNING | 1058 | pr_warn("vmalloc area is too big, limiting to %luMB\n", |
1064 | "vmalloc area is too big, limiting to %luMB\n", | ||
1065 | vmalloc_reserve >> 20); | 1059 | vmalloc_reserve >> 20); |
1066 | } | 1060 | } |
1067 | 1061 | ||
@@ -1094,7 +1088,7 @@ void __init sanity_check_meminfo(void) | |||
1094 | 1088 | ||
1095 | if (highmem) { | 1089 | if (highmem) { |
1096 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", | 1090 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", |
1097 | &block_start, &block_end); | 1091 | &block_start, &block_end); |
1098 | memblock_remove(reg->base, reg->size); | 1092 | memblock_remove(reg->base, reg->size); |
1099 | continue; | 1093 | continue; |
1100 | } | 1094 | } |
@@ -1103,7 +1097,7 @@ void __init sanity_check_meminfo(void) | |||
1103 | phys_addr_t overlap_size = reg->size - size_limit; | 1097 | phys_addr_t overlap_size = reg->size - size_limit; |
1104 | 1098 | ||
1105 | pr_notice("Truncating RAM at %pa-%pa to -%pa", | 1099 | pr_notice("Truncating RAM at %pa-%pa to -%pa", |
1106 | &block_start, &block_end, &vmalloc_limit); | 1100 | &block_start, &block_end, &vmalloc_limit); |
1107 | memblock_remove(vmalloc_limit, overlap_size); | 1101 | memblock_remove(vmalloc_limit, overlap_size); |
1108 | block_end = vmalloc_limit; | 1102 | block_end = vmalloc_limit; |
1109 | } | 1103 | } |
@@ -1326,10 +1320,10 @@ static void __init kmap_init(void) | |||
1326 | #ifdef CONFIG_HIGHMEM | 1320 | #ifdef CONFIG_HIGHMEM |
1327 | pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), | 1321 | pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), |
1328 | PKMAP_BASE, _PAGE_KERNEL_TABLE); | 1322 | PKMAP_BASE, _PAGE_KERNEL_TABLE); |
1329 | |||
1330 | fixmap_page_table = early_pte_alloc(pmd_off_k(FIXADDR_START), | ||
1331 | FIXADDR_START, _PAGE_KERNEL_TABLE); | ||
1332 | #endif | 1323 | #endif |
1324 | |||
1325 | early_pte_alloc(pmd_off_k(FIXADDR_START), FIXADDR_START, | ||
1326 | _PAGE_KERNEL_TABLE); | ||
1333 | } | 1327 | } |
1334 | 1328 | ||
1335 | static void __init map_lowmem(void) | 1329 | static void __init map_lowmem(void) |
@@ -1349,13 +1343,20 @@ static void __init map_lowmem(void) | |||
1349 | if (start >= end) | 1343 | if (start >= end) |
1350 | break; | 1344 | break; |
1351 | 1345 | ||
1352 | if (end < kernel_x_start || start >= kernel_x_end) { | 1346 | if (end < kernel_x_start) { |
1353 | map.pfn = __phys_to_pfn(start); | 1347 | map.pfn = __phys_to_pfn(start); |
1354 | map.virtual = __phys_to_virt(start); | 1348 | map.virtual = __phys_to_virt(start); |
1355 | map.length = end - start; | 1349 | map.length = end - start; |
1356 | map.type = MT_MEMORY_RWX; | 1350 | map.type = MT_MEMORY_RWX; |
1357 | 1351 | ||
1358 | create_mapping(&map); | 1352 | create_mapping(&map); |
1353 | } else if (start >= kernel_x_end) { | ||
1354 | map.pfn = __phys_to_pfn(start); | ||
1355 | map.virtual = __phys_to_virt(start); | ||
1356 | map.length = end - start; | ||
1357 | map.type = MT_MEMORY_RW; | ||
1358 | |||
1359 | create_mapping(&map); | ||
1359 | } else { | 1360 | } else { |
1360 | /* This better cover the entire kernel */ | 1361 | /* This better cover the entire kernel */ |
1361 | if (start < kernel_x_start) { | 1362 | if (start < kernel_x_start) { |
diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c new file mode 100644 index 000000000000..004e35cdcfff --- /dev/null +++ b/arch/arm/mm/pageattr.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/module.h> | ||
15 | |||
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/tlbflush.h> | ||
18 | |||
19 | struct page_change_data { | ||
20 | pgprot_t set_mask; | ||
21 | pgprot_t clear_mask; | ||
22 | }; | ||
23 | |||
24 | static int change_page_range(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
25 | void *data) | ||
26 | { | ||
27 | struct page_change_data *cdata = data; | ||
28 | pte_t pte = *ptep; | ||
29 | |||
30 | pte = clear_pte_bit(pte, cdata->clear_mask); | ||
31 | pte = set_pte_bit(pte, cdata->set_mask); | ||
32 | |||
33 | set_pte_ext(ptep, pte, 0); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int change_memory_common(unsigned long addr, int numpages, | ||
38 | pgprot_t set_mask, pgprot_t clear_mask) | ||
39 | { | ||
40 | unsigned long start = addr; | ||
41 | unsigned long size = PAGE_SIZE*numpages; | ||
42 | unsigned long end = start + size; | ||
43 | int ret; | ||
44 | struct page_change_data data; | ||
45 | |||
46 | if (!IS_ALIGNED(addr, PAGE_SIZE)) { | ||
47 | start &= PAGE_MASK; | ||
48 | end = start + size; | ||
49 | WARN_ON_ONCE(1); | ||
50 | } | ||
51 | |||
52 | if (!is_module_address(start) || !is_module_address(end - 1)) | ||
53 | return -EINVAL; | ||
54 | |||
55 | data.set_mask = set_mask; | ||
56 | data.clear_mask = clear_mask; | ||
57 | |||
58 | ret = apply_to_page_range(&init_mm, start, size, change_page_range, | ||
59 | &data); | ||
60 | |||
61 | flush_tlb_kernel_range(start, end); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | int set_memory_ro(unsigned long addr, int numpages) | ||
66 | { | ||
67 | return change_memory_common(addr, numpages, | ||
68 | __pgprot(L_PTE_RDONLY), | ||
69 | __pgprot(0)); | ||
70 | } | ||
71 | |||
72 | int set_memory_rw(unsigned long addr, int numpages) | ||
73 | { | ||
74 | return change_memory_common(addr, numpages, | ||
75 | __pgprot(0), | ||
76 | __pgprot(L_PTE_RDONLY)); | ||
77 | } | ||
78 | |||
79 | int set_memory_nx(unsigned long addr, int numpages) | ||
80 | { | ||
81 | return change_memory_common(addr, numpages, | ||
82 | __pgprot(L_PTE_XN), | ||
83 | __pgprot(0)); | ||
84 | } | ||
85 | |||
86 | int set_memory_x(unsigned long addr, int numpages) | ||
87 | { | ||
88 | return change_memory_common(addr, numpages, | ||
89 | __pgprot(0), | ||
90 | __pgprot(L_PTE_XN)); | ||
91 | } | ||
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 22ac2a6fbfe3..8b4ee5e81c14 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -591,9 +591,10 @@ __krait_proc_info: | |||
591 | /* | 591 | /* |
592 | * Some Krait processors don't indicate support for SDIV and UDIV | 592 | * Some Krait processors don't indicate support for SDIV and UDIV |
593 | * instructions in the ARM instruction set, even though they actually | 593 | * instructions in the ARM instruction set, even though they actually |
594 | * do support them. | 594 | * do support them. They also don't indicate support for fused multiply |
595 | * instructions even though they actually do support them. | ||
595 | */ | 596 | */ |
596 | __v7_proc __v7_setup, hwcaps = HWCAP_IDIV | 597 | __v7_proc __v7_setup, hwcaps = HWCAP_IDIV | HWCAP_VFPv4 |
597 | .size __krait_proc_info, . - __krait_proc_info | 598 | .size __krait_proc_info, . - __krait_proc_info |
598 | 599 | ||
599 | /* | 600 | /* |
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 4e729f055a81..ec717c190e2c 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c | |||
@@ -86,20 +86,20 @@ extern void nwfpe_enter(void); | |||
86 | static int __init fpe_init(void) | 86 | static int __init fpe_init(void) |
87 | { | 87 | { |
88 | if (sizeof(FPA11) > sizeof(union fp_state)) { | 88 | if (sizeof(FPA11) > sizeof(union fp_state)) { |
89 | printk(KERN_ERR "nwfpe: bad structure size\n"); | 89 | pr_err("nwfpe: bad structure size\n"); |
90 | return -EINVAL; | 90 | return -EINVAL; |
91 | } | 91 | } |
92 | 92 | ||
93 | if (sizeof(FPREG) != 12) { | 93 | if (sizeof(FPREG) != 12) { |
94 | printk(KERN_ERR "nwfpe: bad register size\n"); | 94 | pr_err("nwfpe: bad register size\n"); |
95 | return -EINVAL; | 95 | return -EINVAL; |
96 | } | 96 | } |
97 | if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) | 97 | if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) |
98 | return 0; | 98 | return 0; |
99 | 99 | ||
100 | /* Display title, version and copyright information. */ | 100 | /* Display title, version and copyright information. */ |
101 | printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" | 101 | pr_info("NetWinder Floating Point Emulator V0.97 (" |
102 | NWFPE_BITS " precision)\n"); | 102 | NWFPE_BITS " precision)\n"); |
103 | 103 | ||
104 | thread_register_notifier(&nwfpe_notifier_block); | 104 | thread_register_notifier(&nwfpe_notifier_block); |
105 | 105 | ||
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index cda654cbf2c2..f74a8f7e5f84 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S | |||
@@ -197,6 +197,12 @@ look_for_VFP_exceptions: | |||
197 | tst r5, #FPSCR_IXE | 197 | tst r5, #FPSCR_IXE |
198 | bne process_exception | 198 | bne process_exception |
199 | 199 | ||
200 | tst r5, #FPSCR_LENGTH_MASK | ||
201 | beq skip | ||
202 | orr r1, r1, #FPEXC_DEX | ||
203 | b process_exception | ||
204 | skip: | ||
205 | |||
200 | @ Fall into hand on to next handler - appropriate coproc instr | 206 | @ Fall into hand on to next handler - appropriate coproc instr |
201 | @ not recognised by VFP | 207 | @ not recognised by VFP |
202 | 208 | ||
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2f37e1d6cb45..f6e4d56eda00 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -738,63 +738,73 @@ static int __init vfp_init(void) | |||
738 | vfp_vector = vfp_null_entry; | 738 | vfp_vector = vfp_null_entry; |
739 | 739 | ||
740 | pr_info("VFP support v0.3: "); | 740 | pr_info("VFP support v0.3: "); |
741 | if (VFP_arch) | 741 | if (VFP_arch) { |
742 | pr_cont("not present\n"); | 742 | pr_cont("not present\n"); |
743 | else if (vfpsid & FPSID_NODOUBLE) { | 743 | return 0; |
744 | pr_cont("no double precision support\n"); | 744 | /* Extract the architecture on CPUID scheme */ |
745 | } else { | 745 | } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { |
746 | hotcpu_notifier(vfp_hotplug, 0); | 746 | VFP_arch = vfpsid & FPSID_CPUID_ARCH_MASK; |
747 | 747 | VFP_arch >>= FPSID_ARCH_BIT; | |
748 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | ||
749 | pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", | ||
750 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, | ||
751 | (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT, | ||
752 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, | ||
753 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, | ||
754 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); | ||
755 | |||
756 | vfp_vector = vfp_support_entry; | ||
757 | |||
758 | thread_register_notifier(&vfp_notifier_block); | ||
759 | vfp_pm_init(); | ||
760 | |||
761 | /* | ||
762 | * We detected VFP, and the support code is | ||
763 | * in place; report VFP support to userspace. | ||
764 | */ | ||
765 | elf_hwcap |= HWCAP_VFP; | ||
766 | #ifdef CONFIG_VFPv3 | ||
767 | if (VFP_arch >= 2) { | ||
768 | elf_hwcap |= HWCAP_VFPv3; | ||
769 | |||
770 | /* | ||
771 | * Check for VFPv3 D16 and VFPv4 D16. CPUs in | ||
772 | * this configuration only have 16 x 64bit | ||
773 | * registers. | ||
774 | */ | ||
775 | if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) | ||
776 | elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ | ||
777 | else | ||
778 | elf_hwcap |= HWCAP_VFPD32; | ||
779 | } | ||
780 | #endif | ||
781 | /* | 748 | /* |
782 | * Check for the presence of the Advanced SIMD | 749 | * Check for the presence of the Advanced SIMD |
783 | * load/store instructions, integer and single | 750 | * load/store instructions, integer and single |
784 | * precision floating point operations. Only check | 751 | * precision floating point operations. Only check |
785 | * for NEON if the hardware has the MVFR registers. | 752 | * for NEON if the hardware has the MVFR registers. |
786 | */ | 753 | */ |
787 | if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { | 754 | if (IS_ENABLED(CONFIG_NEON) && |
788 | #ifdef CONFIG_NEON | 755 | (fmrx(MVFR1) & 0x000fff00) == 0x00011100) |
789 | if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) | 756 | elf_hwcap |= HWCAP_NEON; |
790 | elf_hwcap |= HWCAP_NEON; | 757 | |
791 | #endif | 758 | if (IS_ENABLED(CONFIG_VFPv3)) { |
792 | #ifdef CONFIG_VFPv3 | 759 | u32 mvfr0 = fmrx(MVFR0); |
760 | if (((mvfr0 & MVFR0_DP_MASK) >> MVFR0_DP_BIT) == 0x2 || | ||
761 | ((mvfr0 & MVFR0_SP_MASK) >> MVFR0_SP_BIT) == 0x2) { | ||
762 | elf_hwcap |= HWCAP_VFPv3; | ||
763 | /* | ||
764 | * Check for VFPv3 D16 and VFPv4 D16. CPUs in | ||
765 | * this configuration only have 16 x 64bit | ||
766 | * registers. | ||
767 | */ | ||
768 | if ((mvfr0 & MVFR0_A_SIMD_MASK) == 1) | ||
769 | /* also v4-D16 */ | ||
770 | elf_hwcap |= HWCAP_VFPv3D16; | ||
771 | else | ||
772 | elf_hwcap |= HWCAP_VFPD32; | ||
773 | } | ||
774 | |||
793 | if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) | 775 | if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) |
794 | elf_hwcap |= HWCAP_VFPv4; | 776 | elf_hwcap |= HWCAP_VFPv4; |
795 | #endif | ||
796 | } | 777 | } |
778 | /* Extract the architecture version on pre-cpuid scheme */ | ||
779 | } else { | ||
780 | if (vfpsid & FPSID_NODOUBLE) { | ||
781 | pr_cont("no double precision support\n"); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; | ||
797 | } | 786 | } |
787 | |||
788 | hotcpu_notifier(vfp_hotplug, 0); | ||
789 | |||
790 | vfp_vector = vfp_support_entry; | ||
791 | |||
792 | thread_register_notifier(&vfp_notifier_block); | ||
793 | vfp_pm_init(); | ||
794 | |||
795 | /* | ||
796 | * We detected VFP, and the support code is | ||
797 | * in place; report VFP support to userspace. | ||
798 | */ | ||
799 | elf_hwcap |= HWCAP_VFP; | ||
800 | |||
801 | pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", | ||
802 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, | ||
803 | VFP_arch, | ||
804 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, | ||
805 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, | ||
806 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); | ||
807 | |||
798 | return 0; | 808 | return 0; |
799 | } | 809 | } |
800 | 810 | ||
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index 4f96c1617aae..f0465ba0f221 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c | |||
@@ -290,7 +290,7 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) | |||
290 | u32 z, a; | 290 | u32 z, a; |
291 | 291 | ||
292 | if ((significand & 0xc0000000) != 0x40000000) { | 292 | if ((significand & 0xc0000000) != 0x40000000) { |
293 | printk(KERN_WARNING "VFP: estimate_sqrt: invalid significand\n"); | 293 | pr_warn("VFP: estimate_sqrt: invalid significand\n"); |
294 | } | 294 | } |
295 | 295 | ||
296 | a = significand << 1; | 296 | a = significand << 1; |
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 973a3332a85f..80f4de729a86 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c | |||
@@ -95,8 +95,12 @@ static int amba_pm_runtime_suspend(struct device *dev) | |||
95 | struct amba_device *pcdev = to_amba_device(dev); | 95 | struct amba_device *pcdev = to_amba_device(dev); |
96 | int ret = pm_generic_runtime_suspend(dev); | 96 | int ret = pm_generic_runtime_suspend(dev); |
97 | 97 | ||
98 | if (ret == 0 && dev->driver) | 98 | if (ret == 0 && dev->driver) { |
99 | clk_disable_unprepare(pcdev->pclk); | 99 | if (pm_runtime_is_irq_safe(dev)) |
100 | clk_disable(pcdev->pclk); | ||
101 | else | ||
102 | clk_disable_unprepare(pcdev->pclk); | ||
103 | } | ||
100 | 104 | ||
101 | return ret; | 105 | return ret; |
102 | } | 106 | } |
@@ -107,7 +111,10 @@ static int amba_pm_runtime_resume(struct device *dev) | |||
107 | int ret; | 111 | int ret; |
108 | 112 | ||
109 | if (dev->driver) { | 113 | if (dev->driver) { |
110 | ret = clk_prepare_enable(pcdev->pclk); | 114 | if (pm_runtime_is_irq_safe(dev)) |
115 | ret = clk_enable(pcdev->pclk); | ||
116 | else | ||
117 | ret = clk_prepare_enable(pcdev->pclk); | ||
111 | /* Failure is probably fatal to the system, but... */ | 118 | /* Failure is probably fatal to the system, but... */ |
112 | if (ret) | 119 | if (ret) |
113 | return ret; | 120 | return ret; |
@@ -115,7 +122,7 @@ static int amba_pm_runtime_resume(struct device *dev) | |||
115 | 122 | ||
116 | return pm_generic_runtime_resume(dev); | 123 | return pm_generic_runtime_resume(dev); |
117 | } | 124 | } |
118 | #endif | 125 | #endif /* CONFIG_PM */ |
119 | 126 | ||
120 | static const struct dev_pm_ops amba_pm = { | 127 | static const struct dev_pm_ops amba_pm = { |
121 | .suspend = pm_generic_suspend, | 128 | .suspend = pm_generic_suspend, |
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 025b905f6db2..bdf40b530032 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_dma.h> | 28 | #include <linux/of_dma.h> |
29 | #include <linux/err.h> | 29 | #include <linux/err.h> |
30 | #include <linux/pm_runtime.h> | ||
30 | 31 | ||
31 | #include "dmaengine.h" | 32 | #include "dmaengine.h" |
32 | #define PL330_MAX_CHAN 8 | 33 | #define PL330_MAX_CHAN 8 |
@@ -265,6 +266,9 @@ static unsigned cmd_line; | |||
265 | 266 | ||
266 | #define NR_DEFAULT_DESC 16 | 267 | #define NR_DEFAULT_DESC 16 |
267 | 268 | ||
269 | /* Delay for runtime PM autosuspend, ms */ | ||
270 | #define PL330_AUTOSUSPEND_DELAY 20 | ||
271 | |||
268 | /* Populated by the PL330 core driver for DMA API driver's info */ | 272 | /* Populated by the PL330 core driver for DMA API driver's info */ |
269 | struct pl330_config { | 273 | struct pl330_config { |
270 | u32 periph_id; | 274 | u32 periph_id; |
@@ -1958,6 +1962,7 @@ static void pl330_tasklet(unsigned long data) | |||
1958 | struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; | 1962 | struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; |
1959 | struct dma_pl330_desc *desc, *_dt; | 1963 | struct dma_pl330_desc *desc, *_dt; |
1960 | unsigned long flags; | 1964 | unsigned long flags; |
1965 | bool power_down = false; | ||
1961 | 1966 | ||
1962 | spin_lock_irqsave(&pch->lock, flags); | 1967 | spin_lock_irqsave(&pch->lock, flags); |
1963 | 1968 | ||
@@ -1972,10 +1977,17 @@ static void pl330_tasklet(unsigned long data) | |||
1972 | /* Try to submit a req imm. next to the last completed cookie */ | 1977 | /* Try to submit a req imm. next to the last completed cookie */ |
1973 | fill_queue(pch); | 1978 | fill_queue(pch); |
1974 | 1979 | ||
1975 | /* Make sure the PL330 Channel thread is active */ | 1980 | if (list_empty(&pch->work_list)) { |
1976 | spin_lock(&pch->thread->dmac->lock); | 1981 | spin_lock(&pch->thread->dmac->lock); |
1977 | _start(pch->thread); | 1982 | _stop(pch->thread); |
1978 | spin_unlock(&pch->thread->dmac->lock); | 1983 | spin_unlock(&pch->thread->dmac->lock); |
1984 | power_down = true; | ||
1985 | } else { | ||
1986 | /* Make sure the PL330 Channel thread is active */ | ||
1987 | spin_lock(&pch->thread->dmac->lock); | ||
1988 | _start(pch->thread); | ||
1989 | spin_unlock(&pch->thread->dmac->lock); | ||
1990 | } | ||
1979 | 1991 | ||
1980 | while (!list_empty(&pch->completed_list)) { | 1992 | while (!list_empty(&pch->completed_list)) { |
1981 | dma_async_tx_callback callback; | 1993 | dma_async_tx_callback callback; |
@@ -1990,6 +2002,12 @@ static void pl330_tasklet(unsigned long data) | |||
1990 | if (pch->cyclic) { | 2002 | if (pch->cyclic) { |
1991 | desc->status = PREP; | 2003 | desc->status = PREP; |
1992 | list_move_tail(&desc->node, &pch->work_list); | 2004 | list_move_tail(&desc->node, &pch->work_list); |
2005 | if (power_down) { | ||
2006 | spin_lock(&pch->thread->dmac->lock); | ||
2007 | _start(pch->thread); | ||
2008 | spin_unlock(&pch->thread->dmac->lock); | ||
2009 | power_down = false; | ||
2010 | } | ||
1993 | } else { | 2011 | } else { |
1994 | desc->status = FREE; | 2012 | desc->status = FREE; |
1995 | list_move_tail(&desc->node, &pch->dmac->desc_pool); | 2013 | list_move_tail(&desc->node, &pch->dmac->desc_pool); |
@@ -2004,6 +2022,12 @@ static void pl330_tasklet(unsigned long data) | |||
2004 | } | 2022 | } |
2005 | } | 2023 | } |
2006 | spin_unlock_irqrestore(&pch->lock, flags); | 2024 | spin_unlock_irqrestore(&pch->lock, flags); |
2025 | |||
2026 | /* If work list empty, power down */ | ||
2027 | if (power_down) { | ||
2028 | pm_runtime_mark_last_busy(pch->dmac->ddma.dev); | ||
2029 | pm_runtime_put_autosuspend(pch->dmac->ddma.dev); | ||
2030 | } | ||
2007 | } | 2031 | } |
2008 | 2032 | ||
2009 | bool pl330_filter(struct dma_chan *chan, void *param) | 2033 | bool pl330_filter(struct dma_chan *chan, void *param) |
@@ -2073,6 +2097,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned | |||
2073 | 2097 | ||
2074 | switch (cmd) { | 2098 | switch (cmd) { |
2075 | case DMA_TERMINATE_ALL: | 2099 | case DMA_TERMINATE_ALL: |
2100 | pm_runtime_get_sync(pl330->ddma.dev); | ||
2076 | spin_lock_irqsave(&pch->lock, flags); | 2101 | spin_lock_irqsave(&pch->lock, flags); |
2077 | 2102 | ||
2078 | spin_lock(&pl330->lock); | 2103 | spin_lock(&pl330->lock); |
@@ -2099,10 +2124,15 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned | |||
2099 | dma_cookie_complete(&desc->txd); | 2124 | dma_cookie_complete(&desc->txd); |
2100 | } | 2125 | } |
2101 | 2126 | ||
2127 | if (!list_empty(&pch->work_list)) | ||
2128 | pm_runtime_put(pl330->ddma.dev); | ||
2129 | |||
2102 | list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool); | 2130 | list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool); |
2103 | list_splice_tail_init(&pch->work_list, &pl330->desc_pool); | 2131 | list_splice_tail_init(&pch->work_list, &pl330->desc_pool); |
2104 | list_splice_tail_init(&pch->completed_list, &pl330->desc_pool); | 2132 | list_splice_tail_init(&pch->completed_list, &pl330->desc_pool); |
2105 | spin_unlock_irqrestore(&pch->lock, flags); | 2133 | spin_unlock_irqrestore(&pch->lock, flags); |
2134 | pm_runtime_mark_last_busy(pl330->ddma.dev); | ||
2135 | pm_runtime_put_autosuspend(pl330->ddma.dev); | ||
2106 | break; | 2136 | break; |
2107 | case DMA_SLAVE_CONFIG: | 2137 | case DMA_SLAVE_CONFIG: |
2108 | slave_config = (struct dma_slave_config *)arg; | 2138 | slave_config = (struct dma_slave_config *)arg; |
@@ -2138,6 +2168,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan) | |||
2138 | 2168 | ||
2139 | tasklet_kill(&pch->task); | 2169 | tasklet_kill(&pch->task); |
2140 | 2170 | ||
2171 | pm_runtime_get_sync(pch->dmac->ddma.dev); | ||
2141 | spin_lock_irqsave(&pch->lock, flags); | 2172 | spin_lock_irqsave(&pch->lock, flags); |
2142 | 2173 | ||
2143 | pl330_release_channel(pch->thread); | 2174 | pl330_release_channel(pch->thread); |
@@ -2147,6 +2178,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan) | |||
2147 | list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); | 2178 | list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); |
2148 | 2179 | ||
2149 | spin_unlock_irqrestore(&pch->lock, flags); | 2180 | spin_unlock_irqrestore(&pch->lock, flags); |
2181 | pm_runtime_mark_last_busy(pch->dmac->ddma.dev); | ||
2182 | pm_runtime_put_autosuspend(pch->dmac->ddma.dev); | ||
2150 | } | 2183 | } |
2151 | 2184 | ||
2152 | static enum dma_status | 2185 | static enum dma_status |
@@ -2162,6 +2195,15 @@ static void pl330_issue_pending(struct dma_chan *chan) | |||
2162 | unsigned long flags; | 2195 | unsigned long flags; |
2163 | 2196 | ||
2164 | spin_lock_irqsave(&pch->lock, flags); | 2197 | spin_lock_irqsave(&pch->lock, flags); |
2198 | if (list_empty(&pch->work_list)) { | ||
2199 | /* | ||
2200 | * Warn on nothing pending. Empty submitted_list may | ||
2201 | * break our pm_runtime usage counter as it is | ||
2202 | * updated on work_list emptiness status. | ||
2203 | */ | ||
2204 | WARN_ON(list_empty(&pch->submitted_list)); | ||
2205 | pm_runtime_get_sync(pch->dmac->ddma.dev); | ||
2206 | } | ||
2165 | list_splice_tail_init(&pch->submitted_list, &pch->work_list); | 2207 | list_splice_tail_init(&pch->submitted_list, &pch->work_list); |
2166 | spin_unlock_irqrestore(&pch->lock, flags); | 2208 | spin_unlock_irqrestore(&pch->lock, flags); |
2167 | 2209 | ||
@@ -2594,6 +2636,46 @@ static int pl330_dma_device_slave_caps(struct dma_chan *dchan, | |||
2594 | return 0; | 2636 | return 0; |
2595 | } | 2637 | } |
2596 | 2638 | ||
2639 | /* | ||
2640 | * Runtime PM callbacks are provided by amba/bus.c driver. | ||
2641 | * | ||
2642 | * It is assumed here that IRQ safe runtime PM is chosen in probe and amba | ||
2643 | * bus driver will only disable/enable the clock in runtime PM callbacks. | ||
2644 | */ | ||
2645 | static int __maybe_unused pl330_suspend(struct device *dev) | ||
2646 | { | ||
2647 | struct amba_device *pcdev = to_amba_device(dev); | ||
2648 | |||
2649 | pm_runtime_disable(dev); | ||
2650 | |||
2651 | if (!pm_runtime_status_suspended(dev)) { | ||
2652 | /* amba did not disable the clock */ | ||
2653 | amba_pclk_disable(pcdev); | ||
2654 | } | ||
2655 | amba_pclk_unprepare(pcdev); | ||
2656 | |||
2657 | return 0; | ||
2658 | } | ||
2659 | |||
2660 | static int __maybe_unused pl330_resume(struct device *dev) | ||
2661 | { | ||
2662 | struct amba_device *pcdev = to_amba_device(dev); | ||
2663 | int ret; | ||
2664 | |||
2665 | ret = amba_pclk_prepare(pcdev); | ||
2666 | if (ret) | ||
2667 | return ret; | ||
2668 | |||
2669 | if (!pm_runtime_status_suspended(dev)) | ||
2670 | ret = amba_pclk_enable(pcdev); | ||
2671 | |||
2672 | pm_runtime_enable(dev); | ||
2673 | |||
2674 | return ret; | ||
2675 | } | ||
2676 | |||
2677 | static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume); | ||
2678 | |||
2597 | static int | 2679 | static int |
2598 | pl330_probe(struct amba_device *adev, const struct amba_id *id) | 2680 | pl330_probe(struct amba_device *adev, const struct amba_id *id) |
2599 | { | 2681 | { |
@@ -2748,6 +2830,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
2748 | pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan, | 2830 | pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan, |
2749 | pcfg->num_peri, pcfg->num_events); | 2831 | pcfg->num_peri, pcfg->num_events); |
2750 | 2832 | ||
2833 | pm_runtime_irq_safe(&adev->dev); | ||
2834 | pm_runtime_use_autosuspend(&adev->dev); | ||
2835 | pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY); | ||
2836 | pm_runtime_mark_last_busy(&adev->dev); | ||
2837 | pm_runtime_put_autosuspend(&adev->dev); | ||
2838 | |||
2751 | return 0; | 2839 | return 0; |
2752 | probe_err3: | 2840 | probe_err3: |
2753 | /* Idle the DMAC */ | 2841 | /* Idle the DMAC */ |
@@ -2774,6 +2862,8 @@ static int pl330_remove(struct amba_device *adev) | |||
2774 | struct pl330_dmac *pl330 = amba_get_drvdata(adev); | 2862 | struct pl330_dmac *pl330 = amba_get_drvdata(adev); |
2775 | struct dma_pl330_chan *pch, *_p; | 2863 | struct dma_pl330_chan *pch, *_p; |
2776 | 2864 | ||
2865 | pm_runtime_get_noresume(pl330->ddma.dev); | ||
2866 | |||
2777 | if (adev->dev.of_node) | 2867 | if (adev->dev.of_node) |
2778 | of_dma_controller_free(adev->dev.of_node); | 2868 | of_dma_controller_free(adev->dev.of_node); |
2779 | 2869 | ||
@@ -2812,6 +2902,7 @@ static struct amba_driver pl330_driver = { | |||
2812 | .drv = { | 2902 | .drv = { |
2813 | .owner = THIS_MODULE, | 2903 | .owner = THIS_MODULE, |
2814 | .name = "dma-pl330", | 2904 | .name = "dma-pl330", |
2905 | .pm = &pl330_pm, | ||
2815 | }, | 2906 | }, |
2816 | .id_table = pl330_ids, | 2907 | .id_table = pl330_ids, |
2817 | .probe = pl330_probe, | 2908 | .probe = pl330_probe, |
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index ff8a027a4afb..d2ab06048169 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c | |||
@@ -93,6 +93,7 @@ static int sa11x0_drv_pcmcia_remove(struct platform_device *dev) | |||
93 | for (i = 0; i < sinfo->nskt; i++) | 93 | for (i = 0; i < sinfo->nskt; i++) |
94 | soc_pcmcia_remove_one(&sinfo->skt[i]); | 94 | soc_pcmcia_remove_one(&sinfo->skt[i]); |
95 | 95 | ||
96 | clk_put(sinfo->clk); | ||
96 | kfree(sinfo); | 97 | kfree(sinfo); |
97 | return 0; | 98 | return 0; |
98 | } | 99 | } |
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 65b02c3e14ce..7bae7e549d8b 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c | |||
@@ -145,6 +145,12 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, | |||
145 | return -ENOMEM; | 145 | return -ENOMEM; |
146 | 146 | ||
147 | s->soc.nr = ops->first + i; | 147 | s->soc.nr = ops->first + i; |
148 | s->soc.clk = clk_get(&dev->dev, NULL); | ||
149 | if (IS_ERR(s->soc.clk)) { | ||
150 | ret = PTR_ERR(s->soc.clk); | ||
151 | kfree(s); | ||
152 | return ret; | ||
153 | } | ||
148 | soc_pcmcia_init_one(&s->soc, ops, &dev->dev); | 154 | soc_pcmcia_init_one(&s->soc, ops, &dev->dev); |
149 | s->dev = dev; | 155 | s->dev = dev; |
150 | if (s->soc.nr) { | 156 | if (s->soc.nr) { |
@@ -220,6 +226,7 @@ static int pcmcia_remove(struct sa1111_dev *dev) | |||
220 | for (; s; s = next) { | 226 | for (; s; s = next) { |
221 | next = s->next; | 227 | next = s->next; |
222 | soc_pcmcia_remove_one(&s->soc); | 228 | soc_pcmcia_remove_one(&s->soc); |
229 | clk_put(s->soc.clk); | ||
223 | kfree(s); | 230 | kfree(s); |
224 | } | 231 | } |
225 | 232 | ||
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index 54d3089d157b..cf6de2c2b329 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c | |||
@@ -135,14 +135,16 @@ sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, | |||
135 | static int | 135 | static int |
136 | sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt) | 136 | sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt) |
137 | { | 137 | { |
138 | return sa1100_pcmcia_set_mecr(skt, cpufreq_get(0)); | 138 | unsigned long clk = clk_get_rate(skt->clk); |
139 | |||
140 | return sa1100_pcmcia_set_mecr(skt, clk / 1000); | ||
139 | } | 141 | } |
140 | 142 | ||
141 | static int | 143 | static int |
142 | sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf) | 144 | sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf) |
143 | { | 145 | { |
144 | struct soc_pcmcia_timing timing; | 146 | struct soc_pcmcia_timing timing; |
145 | unsigned int clock = cpufreq_get(0); | 147 | unsigned int clock = clk_get_rate(skt->clk); |
146 | unsigned long mecr = MECR; | 148 | unsigned long mecr = MECR; |
147 | char *p = buf; | 149 | char *p = buf; |
148 | 150 | ||
@@ -218,6 +220,11 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, | |||
218 | struct skt_dev_info *sinfo; | 220 | struct skt_dev_info *sinfo; |
219 | struct soc_pcmcia_socket *skt; | 221 | struct soc_pcmcia_socket *skt; |
220 | int i, ret = 0; | 222 | int i, ret = 0; |
223 | struct clk *clk; | ||
224 | |||
225 | clk = clk_get(dev, NULL); | ||
226 | if (IS_ERR(clk)) | ||
227 | return PTR_ERR(clk); | ||
221 | 228 | ||
222 | sa11xx_drv_pcmcia_ops(ops); | 229 | sa11xx_drv_pcmcia_ops(ops); |
223 | 230 | ||
@@ -226,12 +233,14 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, | |||
226 | return -ENOMEM; | 233 | return -ENOMEM; |
227 | 234 | ||
228 | sinfo->nskt = nr; | 235 | sinfo->nskt = nr; |
236 | sinfo->clk = clk; | ||
229 | 237 | ||
230 | /* Initialize processor specific parameters */ | 238 | /* Initialize processor specific parameters */ |
231 | for (i = 0; i < nr; i++) { | 239 | for (i = 0; i < nr; i++) { |
232 | skt = &sinfo->skt[i]; | 240 | skt = &sinfo->skt[i]; |
233 | 241 | ||
234 | skt->nr = first + i; | 242 | skt->nr = first + i; |
243 | skt->clk = clk; | ||
235 | soc_pcmcia_init_one(skt, ops, dev); | 244 | soc_pcmcia_init_one(skt, ops, dev); |
236 | 245 | ||
237 | ret = sa11xx_drv_pcmcia_add_one(skt); | 246 | ret = sa11xx_drv_pcmcia_add_one(skt); |
@@ -242,6 +251,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, | |||
242 | if (ret) { | 251 | if (ret) { |
243 | while (--i >= 0) | 252 | while (--i >= 0) |
244 | soc_pcmcia_remove_one(&sinfo->skt[i]); | 253 | soc_pcmcia_remove_one(&sinfo->skt[i]); |
254 | clk_put(clk); | ||
245 | kfree(sinfo); | 255 | kfree(sinfo); |
246 | } else { | 256 | } else { |
247 | dev_set_drvdata(dev, sinfo); | 257 | dev_set_drvdata(dev, sinfo); |
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index a2bc6ee1702e..933f4657515b 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c | |||
@@ -120,6 +120,8 @@ static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt, | |||
120 | 120 | ||
121 | if (skt->ops->hw_shutdown) | 121 | if (skt->ops->hw_shutdown) |
122 | skt->ops->hw_shutdown(skt); | 122 | skt->ops->hw_shutdown(skt); |
123 | |||
124 | clk_disable_unprepare(skt->clk); | ||
123 | } | 125 | } |
124 | 126 | ||
125 | static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | 127 | static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) |
@@ -131,6 +133,8 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | |||
131 | { | 133 | { |
132 | int ret = 0, i; | 134 | int ret = 0, i; |
133 | 135 | ||
136 | clk_prepare_enable(skt->clk); | ||
137 | |||
134 | if (skt->ops->hw_init) { | 138 | if (skt->ops->hw_init) { |
135 | ret = skt->ops->hw_init(skt); | 139 | ret = skt->ops->hw_init(skt); |
136 | if (ret) | 140 | if (ret) |
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 9690216d38ff..c0abe276ee55 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c | |||
@@ -178,6 +178,7 @@ | |||
178 | #include <linux/dma-mapping.h> | 178 | #include <linux/dma-mapping.h> |
179 | #include <linux/mutex.h> | 179 | #include <linux/mutex.h> |
180 | #include <linux/io.h> | 180 | #include <linux/io.h> |
181 | #include <linux/clk.h> | ||
181 | 182 | ||
182 | #include <video/sa1100fb.h> | 183 | #include <video/sa1100fb.h> |
183 | 184 | ||
@@ -416,9 +417,9 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
416 | var->transp.offset); | 417 | var->transp.offset); |
417 | 418 | ||
418 | #ifdef CONFIG_CPU_FREQ | 419 | #ifdef CONFIG_CPU_FREQ |
419 | dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n", | 420 | dev_dbg(fbi->dev, "dma period = %d ps, clock = %ld kHz\n", |
420 | sa1100fb_display_dma_period(var), | 421 | sa1100fb_display_dma_period(var), |
421 | cpufreq_get(smp_processor_id())); | 422 | clk_get_rate(fbi->clk) / 1000); |
422 | #endif | 423 | #endif |
423 | 424 | ||
424 | return 0; | 425 | return 0; |
@@ -592,9 +593,10 @@ static struct fb_ops sa1100fb_ops = { | |||
592 | * Calculate the PCD value from the clock rate (in picoseconds). | 593 | * Calculate the PCD value from the clock rate (in picoseconds). |
593 | * We take account of the PPCR clock setting. | 594 | * We take account of the PPCR clock setting. |
594 | */ | 595 | */ |
595 | static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock) | 596 | static inline unsigned int get_pcd(struct sa1100fb_info *fbi, |
597 | unsigned int pixclock) | ||
596 | { | 598 | { |
597 | unsigned int pcd = cpuclock / 100; | 599 | unsigned int pcd = clk_get_rate(fbi->clk) / 100 / 1000; |
598 | 600 | ||
599 | pcd *= pixclock; | 601 | pcd *= pixclock; |
600 | pcd /= 10000000; | 602 | pcd /= 10000000; |
@@ -673,7 +675,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_ | |||
673 | LCCR2_BegFrmDel(var->upper_margin) + | 675 | LCCR2_BegFrmDel(var->upper_margin) + |
674 | LCCR2_EndFrmDel(var->lower_margin); | 676 | LCCR2_EndFrmDel(var->lower_margin); |
675 | 677 | ||
676 | pcd = get_pcd(var->pixclock, cpufreq_get(0)); | 678 | pcd = get_pcd(fbi, var->pixclock); |
677 | new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 | | 679 | new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 | |
678 | (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | | 680 | (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | |
679 | (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); | 681 | (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); |
@@ -787,6 +789,9 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi) | |||
787 | fbi->palette_cpu[0] &= 0xcfff; | 789 | fbi->palette_cpu[0] &= 0xcfff; |
788 | fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); | 790 | fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); |
789 | 791 | ||
792 | /* enable LCD controller clock */ | ||
793 | clk_prepare_enable(fbi->clk); | ||
794 | |||
790 | /* Sequence from 11.7.10 */ | 795 | /* Sequence from 11.7.10 */ |
791 | writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3); | 796 | writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3); |
792 | writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2); | 797 | writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2); |
@@ -831,6 +836,9 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) | |||
831 | 836 | ||
832 | schedule_timeout(20 * HZ / 1000); | 837 | schedule_timeout(20 * HZ / 1000); |
833 | remove_wait_queue(&fbi->ctrlr_wait, &wait); | 838 | remove_wait_queue(&fbi->ctrlr_wait, &wait); |
839 | |||
840 | /* disable LCD controller clock */ | ||
841 | clk_disable_unprepare(fbi->clk); | ||
834 | } | 842 | } |
835 | 843 | ||
836 | /* | 844 | /* |
@@ -1009,7 +1017,6 @@ sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, | |||
1009 | void *data) | 1017 | void *data) |
1010 | { | 1018 | { |
1011 | struct sa1100fb_info *fbi = TO_INF(nb, freq_transition); | 1019 | struct sa1100fb_info *fbi = TO_INF(nb, freq_transition); |
1012 | struct cpufreq_freqs *f = data; | ||
1013 | u_int pcd; | 1020 | u_int pcd; |
1014 | 1021 | ||
1015 | switch (val) { | 1022 | switch (val) { |
@@ -1018,7 +1025,7 @@ sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, | |||
1018 | break; | 1025 | break; |
1019 | 1026 | ||
1020 | case CPUFREQ_POSTCHANGE: | 1027 | case CPUFREQ_POSTCHANGE: |
1021 | pcd = get_pcd(fbi->fb.var.pixclock, f->new); | 1028 | pcd = get_pcd(fbi, fbi->fb.var.pixclock); |
1022 | fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); | 1029 | fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); |
1023 | set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); | 1030 | set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); |
1024 | break; | 1031 | break; |
@@ -1225,6 +1232,13 @@ static int sa1100fb_probe(struct platform_device *pdev) | |||
1225 | if (!fbi) | 1232 | if (!fbi) |
1226 | goto failed; | 1233 | goto failed; |
1227 | 1234 | ||
1235 | fbi->clk = clk_get(&pdev->dev, NULL); | ||
1236 | if (IS_ERR(fbi->clk)) { | ||
1237 | ret = PTR_ERR(fbi->clk); | ||
1238 | fbi->clk = NULL; | ||
1239 | goto failed; | ||
1240 | } | ||
1241 | |||
1228 | fbi->base = ioremap(res->start, resource_size(res)); | 1242 | fbi->base = ioremap(res->start, resource_size(res)); |
1229 | if (!fbi->base) | 1243 | if (!fbi->base) |
1230 | goto failed; | 1244 | goto failed; |
@@ -1277,6 +1291,8 @@ static int sa1100fb_probe(struct platform_device *pdev) | |||
1277 | failed: | 1291 | failed: |
1278 | if (fbi) | 1292 | if (fbi) |
1279 | iounmap(fbi->base); | 1293 | iounmap(fbi->base); |
1294 | if (fbi->clk) | ||
1295 | clk_put(fbi->clk); | ||
1280 | kfree(fbi); | 1296 | kfree(fbi); |
1281 | release_mem_region(res->start, resource_size(res)); | 1297 | release_mem_region(res->start, resource_size(res)); |
1282 | return ret; | 1298 | return ret; |
diff --git a/drivers/video/fbdev/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h index fc5d4292fad6..0139d13377a5 100644 --- a/drivers/video/fbdev/sa1100fb.h +++ b/drivers/video/fbdev/sa1100fb.h | |||
@@ -68,6 +68,7 @@ struct sa1100fb_info { | |||
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | const struct sa1100fb_mach_info *inf; | 70 | const struct sa1100fb_mach_info *inf; |
71 | struct clk *clk; | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | #define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member) | 74 | #define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member) |
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index c324f5700d1a..ac02f9bd63dc 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h | |||
@@ -97,6 +97,16 @@ void amba_release_regions(struct amba_device *); | |||
97 | #define amba_pclk_disable(d) \ | 97 | #define amba_pclk_disable(d) \ |
98 | do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) | 98 | do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) |
99 | 99 | ||
100 | static inline int amba_pclk_prepare(struct amba_device *dev) | ||
101 | { | ||
102 | return clk_prepare(dev->pclk); | ||
103 | } | ||
104 | |||
105 | static inline void amba_pclk_unprepare(struct amba_device *dev) | ||
106 | { | ||
107 | clk_unprepare(dev->pclk); | ||
108 | } | ||
109 | |||
100 | /* Some drivers don't use the struct amba_device */ | 110 | /* Some drivers don't use the struct amba_device */ |
101 | #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) | 111 | #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) |
102 | #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) | 112 | #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index eda4feede048..30e84d48bfea 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -118,6 +118,11 @@ static inline void pm_runtime_mark_last_busy(struct device *dev) | |||
118 | ACCESS_ONCE(dev->power.last_busy) = jiffies; | 118 | ACCESS_ONCE(dev->power.last_busy) = jiffies; |
119 | } | 119 | } |
120 | 120 | ||
121 | static inline bool pm_runtime_is_irq_safe(struct device *dev) | ||
122 | { | ||
123 | return dev->power.irq_safe; | ||
124 | } | ||
125 | |||
121 | #else /* !CONFIG_PM */ | 126 | #else /* !CONFIG_PM */ |
122 | 127 | ||
123 | static inline bool queue_pm_work(struct work_struct *work) { return false; } | 128 | static inline bool queue_pm_work(struct work_struct *work) { return false; } |
@@ -164,6 +169,7 @@ static inline bool pm_runtime_enabled(struct device *dev) { return false; } | |||
164 | 169 | ||
165 | static inline void pm_runtime_no_callbacks(struct device *dev) {} | 170 | static inline void pm_runtime_no_callbacks(struct device *dev) {} |
166 | static inline void pm_runtime_irq_safe(struct device *dev) {} | 171 | static inline void pm_runtime_irq_safe(struct device *dev) {} |
172 | static inline bool pm_runtime_is_irq_safe(struct device *dev) { return false; } | ||
167 | 173 | ||
168 | static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } | 174 | static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } |
169 | static inline void pm_runtime_mark_last_busy(struct device *dev) {} | 175 | static inline void pm_runtime_mark_last_busy(struct device *dev) {} |