diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 22 | ||||
-rw-r--r-- | arch/arm/mm/copypage-v4mc.c | 9 | ||||
-rw-r--r-- | arch/arm/mm/copypage-v6.c | 20 | ||||
-rw-r--r-- | arch/arm/mm/copypage-xscale.c | 9 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 20 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 3 | ||||
-rw-r--r-- | arch/arm/mm/flush.c | 14 | ||||
-rw-r--r-- | arch/arm/mm/highmem.c | 21 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 4 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 26 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 7 | ||||
-rw-r--r-- | arch/arm/mm/vmregion.c | 76 | ||||
-rw-r--r-- | arch/arm/mm/vmregion.h | 5 |
13 files changed, 161 insertions, 75 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b1e192ba8c24..a53fd2aaa2f4 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -30,13 +30,13 @@ | |||
30 | 30 | ||
31 | static void __iomem *l2x0_base; | 31 | static void __iomem *l2x0_base; |
32 | static DEFINE_RAW_SPINLOCK(l2x0_lock); | 32 | static DEFINE_RAW_SPINLOCK(l2x0_lock); |
33 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ | 33 | static u32 l2x0_way_mask; /* Bitmask of active ways */ |
34 | static uint32_t l2x0_size; | 34 | static u32 l2x0_size; |
35 | 35 | ||
36 | struct l2x0_regs l2x0_saved_regs; | 36 | struct l2x0_regs l2x0_saved_regs; |
37 | 37 | ||
38 | struct l2x0_of_data { | 38 | struct l2x0_of_data { |
39 | void (*setup)(const struct device_node *, __u32 *, __u32 *); | 39 | void (*setup)(const struct device_node *, u32 *, u32 *); |
40 | void (*save)(void); | 40 | void (*save)(void); |
41 | void (*resume)(void); | 41 | void (*resume)(void); |
42 | }; | 42 | }; |
@@ -288,7 +288,7 @@ static void l2x0_disable(void) | |||
288 | raw_spin_unlock_irqrestore(&l2x0_lock, flags); | 288 | raw_spin_unlock_irqrestore(&l2x0_lock, flags); |
289 | } | 289 | } |
290 | 290 | ||
291 | static void l2x0_unlock(__u32 cache_id) | 291 | static void l2x0_unlock(u32 cache_id) |
292 | { | 292 | { |
293 | int lockregs; | 293 | int lockregs; |
294 | int i; | 294 | int i; |
@@ -307,11 +307,11 @@ static void l2x0_unlock(__u32 cache_id) | |||
307 | } | 307 | } |
308 | } | 308 | } |
309 | 309 | ||
310 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | 310 | void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) |
311 | { | 311 | { |
312 | __u32 aux; | 312 | u32 aux; |
313 | __u32 cache_id; | 313 | u32 cache_id; |
314 | __u32 way_size = 0; | 314 | u32 way_size = 0; |
315 | int ways; | 315 | int ways; |
316 | const char *type; | 316 | const char *type; |
317 | 317 | ||
@@ -388,7 +388,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
388 | 388 | ||
389 | #ifdef CONFIG_OF | 389 | #ifdef CONFIG_OF |
390 | static void __init l2x0_of_setup(const struct device_node *np, | 390 | static void __init l2x0_of_setup(const struct device_node *np, |
391 | __u32 *aux_val, __u32 *aux_mask) | 391 | u32 *aux_val, u32 *aux_mask) |
392 | { | 392 | { |
393 | u32 data[2] = { 0, 0 }; | 393 | u32 data[2] = { 0, 0 }; |
394 | u32 tag = 0; | 394 | u32 tag = 0; |
@@ -422,7 +422,7 @@ static void __init l2x0_of_setup(const struct device_node *np, | |||
422 | } | 422 | } |
423 | 423 | ||
424 | static void __init pl310_of_setup(const struct device_node *np, | 424 | static void __init pl310_of_setup(const struct device_node *np, |
425 | __u32 *aux_val, __u32 *aux_mask) | 425 | u32 *aux_val, u32 *aux_mask) |
426 | { | 426 | { |
427 | u32 data[3] = { 0, 0, 0 }; | 427 | u32 data[3] = { 0, 0, 0 }; |
428 | u32 tag[3] = { 0, 0, 0 }; | 428 | u32 tag[3] = { 0, 0, 0 }; |
@@ -548,7 +548,7 @@ static const struct of_device_id l2x0_ids[] __initconst = { | |||
548 | {} | 548 | {} |
549 | }; | 549 | }; |
550 | 550 | ||
551 | int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) | 551 | int __init l2x0_of_init(u32 aux_val, u32 aux_mask) |
552 | { | 552 | { |
553 | struct device_node *np; | 553 | struct device_node *np; |
554 | struct l2x0_of_data *data; | 554 | struct l2x0_of_data *data; |
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index ec8c3befb9c8..1267e64133b9 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c | |||
@@ -23,10 +23,6 @@ | |||
23 | 23 | ||
24 | #include "mm.h" | 24 | #include "mm.h" |
25 | 25 | ||
26 | /* | ||
27 | * 0xffff8000 to 0xffffffff is reserved for any ARM architecture | ||
28 | * specific hacks for copying pages efficiently. | ||
29 | */ | ||
30 | #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ | 26 | #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ |
31 | L_PTE_MT_MINICACHE) | 27 | L_PTE_MT_MINICACHE) |
32 | 28 | ||
@@ -78,10 +74,9 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from, | |||
78 | 74 | ||
79 | raw_spin_lock(&minicache_lock); | 75 | raw_spin_lock(&minicache_lock); |
80 | 76 | ||
81 | set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); | 77 | set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot)); |
82 | flush_tlb_kernel_page(0xffff8000); | ||
83 | 78 | ||
84 | mc_copy_user_page((void *)0xffff8000, kto); | 79 | mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); |
85 | 80 | ||
86 | raw_spin_unlock(&minicache_lock); | 81 | raw_spin_unlock(&minicache_lock); |
87 | 82 | ||
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 8b03a5814d00..b9bcc9d79176 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c | |||
@@ -24,9 +24,6 @@ | |||
24 | #error FIX ME | 24 | #error FIX ME |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #define from_address (0xffff8000) | ||
28 | #define to_address (0xffffc000) | ||
29 | |||
30 | static DEFINE_RAW_SPINLOCK(v6_lock); | 27 | static DEFINE_RAW_SPINLOCK(v6_lock); |
31 | 28 | ||
32 | /* | 29 | /* |
@@ -90,14 +87,11 @@ static void v6_copy_user_highpage_aliasing(struct page *to, | |||
90 | */ | 87 | */ |
91 | raw_spin_lock(&v6_lock); | 88 | raw_spin_lock(&v6_lock); |
92 | 89 | ||
93 | set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0); | 90 | kfrom = COPYPAGE_V6_FROM + (offset << PAGE_SHIFT); |
94 | set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0); | 91 | kto = COPYPAGE_V6_TO + (offset << PAGE_SHIFT); |
95 | |||
96 | kfrom = from_address + (offset << PAGE_SHIFT); | ||
97 | kto = to_address + (offset << PAGE_SHIFT); | ||
98 | 92 | ||
99 | flush_tlb_kernel_page(kfrom); | 93 | set_top_pte(kfrom, mk_pte(from, PAGE_KERNEL)); |
100 | flush_tlb_kernel_page(kto); | 94 | set_top_pte(kto, mk_pte(to, PAGE_KERNEL)); |
101 | 95 | ||
102 | copy_page((void *)kto, (void *)kfrom); | 96 | copy_page((void *)kto, (void *)kfrom); |
103 | 97 | ||
@@ -111,8 +105,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to, | |||
111 | */ | 105 | */ |
112 | static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr) | 106 | static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr) |
113 | { | 107 | { |
114 | unsigned int offset = CACHE_COLOUR(vaddr); | 108 | unsigned long to = COPYPAGE_V6_TO + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); |
115 | unsigned long to = to_address + (offset << PAGE_SHIFT); | ||
116 | 109 | ||
117 | /* FIXME: not highmem safe */ | 110 | /* FIXME: not highmem safe */ |
118 | discard_old_kernel_data(page_address(page)); | 111 | discard_old_kernel_data(page_address(page)); |
@@ -123,8 +116,7 @@ static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vad | |||
123 | */ | 116 | */ |
124 | raw_spin_lock(&v6_lock); | 117 | raw_spin_lock(&v6_lock); |
125 | 118 | ||
126 | set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0); | 119 | set_top_pte(to, mk_pte(page, PAGE_KERNEL)); |
127 | flush_tlb_kernel_page(to); | ||
128 | clear_page((void *)to); | 120 | clear_page((void *)to); |
129 | 121 | ||
130 | raw_spin_unlock(&v6_lock); | 122 | raw_spin_unlock(&v6_lock); |
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index 439d106ae638..0fb85025344d 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c | |||
@@ -23,12 +23,6 @@ | |||
23 | 23 | ||
24 | #include "mm.h" | 24 | #include "mm.h" |
25 | 25 | ||
26 | /* | ||
27 | * 0xffff8000 to 0xffffffff is reserved for any ARM architecture | ||
28 | * specific hacks for copying pages efficiently. | ||
29 | */ | ||
30 | #define COPYPAGE_MINICACHE 0xffff8000 | ||
31 | |||
32 | #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ | 26 | #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ |
33 | L_PTE_MT_MINICACHE) | 27 | L_PTE_MT_MINICACHE) |
34 | 28 | ||
@@ -100,8 +94,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from, | |||
100 | 94 | ||
101 | raw_spin_lock(&minicache_lock); | 95 | raw_spin_lock(&minicache_lock); |
102 | 96 | ||
103 | set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); | 97 | set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot)); |
104 | flush_tlb_kernel_page(COPYPAGE_MINICACHE); | ||
105 | 98 | ||
106 | mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); | 99 | mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); |
107 | 100 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 1aa664a1999f..db23ae4aaaab 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -214,7 +214,8 @@ static int __init consistent_init(void) | |||
214 | core_initcall(consistent_init); | 214 | core_initcall(consistent_init); |
215 | 215 | ||
216 | static void * | 216 | static void * |
217 | __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot) | 217 | __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, |
218 | const void *caller) | ||
218 | { | 219 | { |
219 | struct arm_vmregion *c; | 220 | struct arm_vmregion *c; |
220 | size_t align; | 221 | size_t align; |
@@ -241,7 +242,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot) | |||
241 | * Allocate a virtual address in the consistent mapping region. | 242 | * Allocate a virtual address in the consistent mapping region. |
242 | */ | 243 | */ |
243 | c = arm_vmregion_alloc(&consistent_head, align, size, | 244 | c = arm_vmregion_alloc(&consistent_head, align, size, |
244 | gfp & ~(__GFP_DMA | __GFP_HIGHMEM)); | 245 | gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller); |
245 | if (c) { | 246 | if (c) { |
246 | pte_t *pte; | 247 | pte_t *pte; |
247 | int idx = CONSISTENT_PTE_INDEX(c->vm_start); | 248 | int idx = CONSISTENT_PTE_INDEX(c->vm_start); |
@@ -320,14 +321,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size) | |||
320 | 321 | ||
321 | #else /* !CONFIG_MMU */ | 322 | #else /* !CONFIG_MMU */ |
322 | 323 | ||
323 | #define __dma_alloc_remap(page, size, gfp, prot) page_address(page) | 324 | #define __dma_alloc_remap(page, size, gfp, prot, c) page_address(page) |
324 | #define __dma_free_remap(addr, size) do { } while (0) | 325 | #define __dma_free_remap(addr, size) do { } while (0) |
325 | 326 | ||
326 | #endif /* CONFIG_MMU */ | 327 | #endif /* CONFIG_MMU */ |
327 | 328 | ||
328 | static void * | 329 | static void * |
329 | __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | 330 | __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, |
330 | pgprot_t prot) | 331 | pgprot_t prot, const void *caller) |
331 | { | 332 | { |
332 | struct page *page; | 333 | struct page *page; |
333 | void *addr; | 334 | void *addr; |
@@ -349,7 +350,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | |||
349 | return NULL; | 350 | return NULL; |
350 | 351 | ||
351 | if (!arch_is_coherent()) | 352 | if (!arch_is_coherent()) |
352 | addr = __dma_alloc_remap(page, size, gfp, prot); | 353 | addr = __dma_alloc_remap(page, size, gfp, prot, caller); |
353 | else | 354 | else |
354 | addr = page_address(page); | 355 | addr = page_address(page); |
355 | 356 | ||
@@ -374,7 +375,8 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gf | |||
374 | return memory; | 375 | return memory; |
375 | 376 | ||
376 | return __dma_alloc(dev, size, handle, gfp, | 377 | return __dma_alloc(dev, size, handle, gfp, |
377 | pgprot_dmacoherent(pgprot_kernel)); | 378 | pgprot_dmacoherent(pgprot_kernel), |
379 | __builtin_return_address(0)); | ||
378 | } | 380 | } |
379 | EXPORT_SYMBOL(dma_alloc_coherent); | 381 | EXPORT_SYMBOL(dma_alloc_coherent); |
380 | 382 | ||
@@ -386,7 +388,8 @@ void * | |||
386 | dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) | 388 | dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) |
387 | { | 389 | { |
388 | return __dma_alloc(dev, size, handle, gfp, | 390 | return __dma_alloc(dev, size, handle, gfp, |
389 | pgprot_writecombine(pgprot_kernel)); | 391 | pgprot_writecombine(pgprot_kernel), |
392 | __builtin_return_address(0)); | ||
390 | } | 393 | } |
391 | EXPORT_SYMBOL(dma_alloc_writecombine); | 394 | EXPORT_SYMBOL(dma_alloc_writecombine); |
392 | 395 | ||
@@ -723,6 +726,9 @@ EXPORT_SYMBOL(dma_set_mask); | |||
723 | 726 | ||
724 | static int __init dma_debug_do_init(void) | 727 | static int __init dma_debug_do_init(void) |
725 | { | 728 | { |
729 | #ifdef CONFIG_MMU | ||
730 | arm_vmregion_create_proc("dma-mappings", &consistent_head); | ||
731 | #endif | ||
726 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | 732 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); |
727 | return 0; | 733 | return 0; |
728 | } | 734 | } |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 5bdff5c3e6cb..9055b5a84ec5 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -165,7 +165,8 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, | |||
165 | struct siginfo si; | 165 | struct siginfo si; |
166 | 166 | ||
167 | #ifdef CONFIG_DEBUG_USER | 167 | #ifdef CONFIG_DEBUG_USER |
168 | if (user_debug & UDBG_SEGV) { | 168 | if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) || |
169 | ((user_debug & UDBG_BUS) && (sig == SIGBUS))) { | ||
169 | printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", | 170 | printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", |
170 | tsk->comm, sig, addr, fsr); | 171 | tsk->comm, sig, addr, fsr); |
171 | show_pte(tsk->mm, addr); | 172 | show_pte(tsk->mm, addr); |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 062d61a1f87d..77458548e031 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -22,15 +22,12 @@ | |||
22 | 22 | ||
23 | #ifdef CONFIG_CPU_CACHE_VIPT | 23 | #ifdef CONFIG_CPU_CACHE_VIPT |
24 | 24 | ||
25 | #define ALIAS_FLUSH_START 0xffff4000 | ||
26 | |||
27 | static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) | 25 | static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) |
28 | { | 26 | { |
29 | unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); | 27 | unsigned long to = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); |
30 | const int zero = 0; | 28 | const int zero = 0; |
31 | 29 | ||
32 | set_pte_ext(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL), 0); | 30 | set_top_pte(to, pfn_pte(pfn, PAGE_KERNEL)); |
33 | flush_tlb_kernel_page(to); | ||
34 | 31 | ||
35 | asm( "mcrr p15, 0, %1, %0, c14\n" | 32 | asm( "mcrr p15, 0, %1, %0, c14\n" |
36 | " mcr p15, 0, %2, c7, c10, 4" | 33 | " mcr p15, 0, %2, c7, c10, 4" |
@@ -41,13 +38,12 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) | |||
41 | 38 | ||
42 | static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len) | 39 | static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len) |
43 | { | 40 | { |
44 | unsigned long colour = CACHE_COLOUR(vaddr); | 41 | unsigned long va = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); |
45 | unsigned long offset = vaddr & (PAGE_SIZE - 1); | 42 | unsigned long offset = vaddr & (PAGE_SIZE - 1); |
46 | unsigned long to; | 43 | unsigned long to; |
47 | 44 | ||
48 | set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0); | 45 | set_top_pte(va, pfn_pte(pfn, PAGE_KERNEL)); |
49 | to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset; | 46 | to = va + offset; |
50 | flush_tlb_kernel_page(to); | ||
51 | flush_icache_range(to, to + len); | 47 | flush_icache_range(to, to + len); |
52 | } | 48 | } |
53 | 49 | ||
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 5a21505d7550..21b9e1bf9b77 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
@@ -69,15 +69,14 @@ void *kmap_atomic(struct page *page) | |||
69 | * With debugging enabled, kunmap_atomic forces that entry to 0. | 69 | * With debugging enabled, kunmap_atomic forces that entry to 0. |
70 | * Make sure it was indeed properly unmapped. | 70 | * Make sure it was indeed properly unmapped. |
71 | */ | 71 | */ |
72 | BUG_ON(!pte_none(*(TOP_PTE(vaddr)))); | 72 | BUG_ON(!pte_none(get_top_pte(vaddr))); |
73 | #endif | 73 | #endif |
74 | set_pte_ext(TOP_PTE(vaddr), mk_pte(page, kmap_prot), 0); | ||
75 | /* | 74 | /* |
76 | * When debugging is off, kunmap_atomic leaves the previous mapping | 75 | * When debugging is off, kunmap_atomic leaves the previous mapping |
77 | * in place, so this TLB flush ensures the TLB is updated with the | 76 | * in place, so the contained TLB flush ensures the TLB is updated |
78 | * new mapping. | 77 | * with the new mapping. |
79 | */ | 78 | */ |
80 | local_flush_tlb_kernel_page(vaddr); | 79 | set_top_pte(vaddr, mk_pte(page, kmap_prot)); |
81 | 80 | ||
82 | return (void *)vaddr; | 81 | return (void *)vaddr; |
83 | } | 82 | } |
@@ -96,8 +95,7 @@ void __kunmap_atomic(void *kvaddr) | |||
96 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); | 95 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); |
97 | #ifdef CONFIG_DEBUG_HIGHMEM | 96 | #ifdef CONFIG_DEBUG_HIGHMEM |
98 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | 97 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); |
99 | set_pte_ext(TOP_PTE(vaddr), __pte(0), 0); | 98 | set_top_pte(vaddr, __pte(0)); |
100 | local_flush_tlb_kernel_page(vaddr); | ||
101 | #else | 99 | #else |
102 | (void) idx; /* to kill a warning */ | 100 | (void) idx; /* to kill a warning */ |
103 | #endif | 101 | #endif |
@@ -121,10 +119,9 @@ void *kmap_atomic_pfn(unsigned long pfn) | |||
121 | idx = type + KM_TYPE_NR * smp_processor_id(); | 119 | idx = type + KM_TYPE_NR * smp_processor_id(); |
122 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 120 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
123 | #ifdef CONFIG_DEBUG_HIGHMEM | 121 | #ifdef CONFIG_DEBUG_HIGHMEM |
124 | BUG_ON(!pte_none(*(TOP_PTE(vaddr)))); | 122 | BUG_ON(!pte_none(get_top_pte(vaddr))); |
125 | #endif | 123 | #endif |
126 | set_pte_ext(TOP_PTE(vaddr), pfn_pte(pfn, kmap_prot), 0); | 124 | set_top_pte(vaddr, pfn_pte(pfn, kmap_prot)); |
127 | local_flush_tlb_kernel_page(vaddr); | ||
128 | 125 | ||
129 | return (void *)vaddr; | 126 | return (void *)vaddr; |
130 | } | 127 | } |
@@ -132,11 +129,9 @@ void *kmap_atomic_pfn(unsigned long pfn) | |||
132 | struct page *kmap_atomic_to_page(const void *ptr) | 129 | struct page *kmap_atomic_to_page(const void *ptr) |
133 | { | 130 | { |
134 | unsigned long vaddr = (unsigned long)ptr; | 131 | unsigned long vaddr = (unsigned long)ptr; |
135 | pte_t *pte; | ||
136 | 132 | ||
137 | if (vaddr < FIXADDR_START) | 133 | if (vaddr < FIXADDR_START) |
138 | return virt_to_page(ptr); | 134 | return virt_to_page(ptr); |
139 | 135 | ||
140 | pte = TOP_PTE(vaddr); | 136 | return pte_page(get_top_pte(vaddr)); |
141 | return pte_page(*pte); | ||
142 | } | 137 | } |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 245a55a0a5bb..595079fa9d1d 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -658,7 +658,9 @@ void __init mem_init(void) | |||
658 | #ifdef CONFIG_HIGHMEM | 658 | #ifdef CONFIG_HIGHMEM |
659 | " pkmap : 0x%08lx - 0x%08lx (%4ld MB)\n" | 659 | " pkmap : 0x%08lx - 0x%08lx (%4ld MB)\n" |
660 | #endif | 660 | #endif |
661 | #ifdef CONFIG_MODULES | ||
661 | " modules : 0x%08lx - 0x%08lx (%4ld MB)\n" | 662 | " modules : 0x%08lx - 0x%08lx (%4ld MB)\n" |
663 | #endif | ||
662 | " .text : 0x%p" " - 0x%p" " (%4d kB)\n" | 664 | " .text : 0x%p" " - 0x%p" " (%4d kB)\n" |
663 | " .init : 0x%p" " - 0x%p" " (%4d kB)\n" | 665 | " .init : 0x%p" " - 0x%p" " (%4d kB)\n" |
664 | " .data : 0x%p" " - 0x%p" " (%4d kB)\n" | 666 | " .data : 0x%p" " - 0x%p" " (%4d kB)\n" |
@@ -677,7 +679,9 @@ void __init mem_init(void) | |||
677 | MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) * | 679 | MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) * |
678 | (PAGE_SIZE)), | 680 | (PAGE_SIZE)), |
679 | #endif | 681 | #endif |
682 | #ifdef CONFIG_MODULES | ||
680 | MLM(MODULES_VADDR, MODULES_END), | 683 | MLM(MODULES_VADDR, MODULES_END), |
684 | #endif | ||
681 | 685 | ||
682 | MLK_ROUNDUP(_text, _etext), | 686 | MLK_ROUNDUP(_text, _etext), |
683 | MLK_ROUNDUP(__init_begin, __init_end), | 687 | MLK_ROUNDUP(__init_begin, __init_end), |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 70f6d3ea4834..27f4a619b35d 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -3,7 +3,31 @@ | |||
3 | /* the upper-most page table pointer */ | 3 | /* the upper-most page table pointer */ |
4 | extern pmd_t *top_pmd; | 4 | extern pmd_t *top_pmd; |
5 | 5 | ||
6 | #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) | 6 | /* |
7 | * 0xffff8000 to 0xffffffff is reserved for any ARM architecture | ||
8 | * specific hacks for copying pages efficiently, while 0xffff4000 | ||
9 | * is reserved for VIPT aliasing flushing by generic code. | ||
10 | * | ||
11 | * Note that we don't allow VIPT aliasing caches with SMP. | ||
12 | */ | ||
13 | #define COPYPAGE_MINICACHE 0xffff8000 | ||
14 | #define COPYPAGE_V6_FROM 0xffff8000 | ||
15 | #define COPYPAGE_V6_TO 0xffffc000 | ||
16 | /* PFN alias flushing, for VIPT caches */ | ||
17 | #define FLUSH_ALIAS_START 0xffff4000 | ||
18 | |||
19 | static inline void set_top_pte(unsigned long va, pte_t pte) | ||
20 | { | ||
21 | pte_t *ptep = pte_offset_kernel(top_pmd, va); | ||
22 | set_pte_ext(ptep, pte, 0); | ||
23 | local_flush_tlb_kernel_page(va); | ||
24 | } | ||
25 | |||
26 | static inline pte_t get_top_pte(unsigned long va) | ||
27 | { | ||
28 | pte_t *ptep = pte_offset_kernel(top_pmd, va); | ||
29 | return *ptep; | ||
30 | } | ||
7 | 31 | ||
8 | static inline pmd_t *pmd_off_k(unsigned long virt) | 32 | static inline pmd_t *pmd_off_k(unsigned long virt) |
9 | { | 33 | { |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index cd439c1dd506..b86f8933ff91 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -999,11 +999,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
999 | { | 999 | { |
1000 | struct map_desc map; | 1000 | struct map_desc map; |
1001 | unsigned long addr; | 1001 | unsigned long addr; |
1002 | void *vectors; | ||
1002 | 1003 | ||
1003 | /* | 1004 | /* |
1004 | * Allocate the vector page early. | 1005 | * Allocate the vector page early. |
1005 | */ | 1006 | */ |
1006 | vectors_page = early_alloc(PAGE_SIZE); | 1007 | vectors = early_alloc(PAGE_SIZE); |
1008 | |||
1009 | early_trap_init(vectors); | ||
1007 | 1010 | ||
1008 | for (addr = VMALLOC_START; addr; addr += PMD_SIZE) | 1011 | for (addr = VMALLOC_START; addr; addr += PMD_SIZE) |
1009 | pmd_clear(pmd_off_k(addr)); | 1012 | pmd_clear(pmd_off_k(addr)); |
@@ -1043,7 +1046,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
1043 | * location (0xffff0000). If we aren't using high-vectors, also | 1046 | * location (0xffff0000). If we aren't using high-vectors, also |
1044 | * create a mapping at the low-vectors virtual address. | 1047 | * create a mapping at the low-vectors virtual address. |
1045 | */ | 1048 | */ |
1046 | map.pfn = __phys_to_pfn(virt_to_phys(vectors_page)); | 1049 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); |
1047 | map.virtual = 0xffff0000; | 1050 | map.virtual = 0xffff0000; |
1048 | map.length = PAGE_SIZE; | 1051 | map.length = PAGE_SIZE; |
1049 | map.type = MT_HIGH_VECTORS; | 1052 | map.type = MT_HIGH_VECTORS; |
diff --git a/arch/arm/mm/vmregion.c b/arch/arm/mm/vmregion.c index 036fdbfdd62f..a631016e1f8f 100644 --- a/arch/arm/mm/vmregion.c +++ b/arch/arm/mm/vmregion.c | |||
@@ -1,5 +1,8 @@ | |||
1 | #include <linux/fs.h> | ||
1 | #include <linux/spinlock.h> | 2 | #include <linux/spinlock.h> |
2 | #include <linux/list.h> | 3 | #include <linux/list.h> |
4 | #include <linux/proc_fs.h> | ||
5 | #include <linux/seq_file.h> | ||
3 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
4 | 7 | ||
5 | #include "vmregion.h" | 8 | #include "vmregion.h" |
@@ -36,7 +39,7 @@ | |||
36 | 39 | ||
37 | struct arm_vmregion * | 40 | struct arm_vmregion * |
38 | arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, | 41 | arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, |
39 | size_t size, gfp_t gfp) | 42 | size_t size, gfp_t gfp, const void *caller) |
40 | { | 43 | { |
41 | unsigned long start = head->vm_start, addr = head->vm_end; | 44 | unsigned long start = head->vm_start, addr = head->vm_end; |
42 | unsigned long flags; | 45 | unsigned long flags; |
@@ -52,6 +55,8 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, | |||
52 | if (!new) | 55 | if (!new) |
53 | goto out; | 56 | goto out; |
54 | 57 | ||
58 | new->caller = caller; | ||
59 | |||
55 | spin_lock_irqsave(&head->vm_lock, flags); | 60 | spin_lock_irqsave(&head->vm_lock, flags); |
56 | 61 | ||
57 | addr = rounddown(addr - size, align); | 62 | addr = rounddown(addr - size, align); |
@@ -129,3 +134,72 @@ void arm_vmregion_free(struct arm_vmregion_head *head, struct arm_vmregion *c) | |||
129 | 134 | ||
130 | kfree(c); | 135 | kfree(c); |
131 | } | 136 | } |
137 | |||
138 | #ifdef CONFIG_PROC_FS | ||
139 | static int arm_vmregion_show(struct seq_file *m, void *p) | ||
140 | { | ||
141 | struct arm_vmregion *c = list_entry(p, struct arm_vmregion, vm_list); | ||
142 | |||
143 | seq_printf(m, "0x%08lx-0x%08lx %7lu", c->vm_start, c->vm_end, | ||
144 | c->vm_end - c->vm_start); | ||
145 | if (c->caller) | ||
146 | seq_printf(m, " %pS", (void *)c->caller); | ||
147 | seq_putc(m, '\n'); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static void *arm_vmregion_start(struct seq_file *m, loff_t *pos) | ||
152 | { | ||
153 | struct arm_vmregion_head *h = m->private; | ||
154 | spin_lock_irq(&h->vm_lock); | ||
155 | return seq_list_start(&h->vm_list, *pos); | ||
156 | } | ||
157 | |||
158 | static void *arm_vmregion_next(struct seq_file *m, void *p, loff_t *pos) | ||
159 | { | ||
160 | struct arm_vmregion_head *h = m->private; | ||
161 | return seq_list_next(p, &h->vm_list, pos); | ||
162 | } | ||
163 | |||
164 | static void arm_vmregion_stop(struct seq_file *m, void *p) | ||
165 | { | ||
166 | struct arm_vmregion_head *h = m->private; | ||
167 | spin_unlock_irq(&h->vm_lock); | ||
168 | } | ||
169 | |||
170 | static const struct seq_operations arm_vmregion_ops = { | ||
171 | .start = arm_vmregion_start, | ||
172 | .stop = arm_vmregion_stop, | ||
173 | .next = arm_vmregion_next, | ||
174 | .show = arm_vmregion_show, | ||
175 | }; | ||
176 | |||
177 | static int arm_vmregion_open(struct inode *inode, struct file *file) | ||
178 | { | ||
179 | struct arm_vmregion_head *h = PDE(inode)->data; | ||
180 | int ret = seq_open(file, &arm_vmregion_ops); | ||
181 | if (!ret) { | ||
182 | struct seq_file *m = file->private_data; | ||
183 | m->private = h; | ||
184 | } | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static const struct file_operations arm_vmregion_fops = { | ||
189 | .open = arm_vmregion_open, | ||
190 | .read = seq_read, | ||
191 | .llseek = seq_lseek, | ||
192 | .release = seq_release, | ||
193 | }; | ||
194 | |||
195 | int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h) | ||
196 | { | ||
197 | proc_create_data(path, S_IRUSR, NULL, &arm_vmregion_fops, h); | ||
198 | return 0; | ||
199 | } | ||
200 | #else | ||
201 | int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h) | ||
202 | { | ||
203 | return 0; | ||
204 | } | ||
205 | #endif | ||
diff --git a/arch/arm/mm/vmregion.h b/arch/arm/mm/vmregion.h index 15e9f044db9f..162be662c088 100644 --- a/arch/arm/mm/vmregion.h +++ b/arch/arm/mm/vmregion.h | |||
@@ -19,11 +19,14 @@ struct arm_vmregion { | |||
19 | unsigned long vm_end; | 19 | unsigned long vm_end; |
20 | struct page *vm_pages; | 20 | struct page *vm_pages; |
21 | int vm_active; | 21 | int vm_active; |
22 | const void *caller; | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t); | 25 | struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t, const void *); |
25 | struct arm_vmregion *arm_vmregion_find(struct arm_vmregion_head *, unsigned long); | 26 | struct arm_vmregion *arm_vmregion_find(struct arm_vmregion_head *, unsigned long); |
26 | struct arm_vmregion *arm_vmregion_find_remove(struct arm_vmregion_head *, unsigned long); | 27 | struct arm_vmregion *arm_vmregion_find_remove(struct arm_vmregion_head *, unsigned long); |
27 | void arm_vmregion_free(struct arm_vmregion_head *, struct arm_vmregion *); | 28 | void arm_vmregion_free(struct arm_vmregion_head *, struct arm_vmregion *); |
28 | 29 | ||
30 | int arm_vmregion_create_proc(const char *, struct arm_vmregion_head *); | ||
31 | |||
29 | #endif | 32 | #endif |