diff options
Diffstat (limited to 'arch/arm/mm/highmem.c')
| -rw-r--r-- | arch/arm/mm/highmem.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 21b9e1bf9b77..45aeaaca9052 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
| @@ -18,6 +18,21 @@ | |||
| 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) | ||
| 24 | { | ||
| 25 | unsigned long vaddr = __fix_to_virt(idx); | ||
| 26 | set_pte_ext(fixmap_page_table + idx, pte, 0); | ||
| 27 | local_flush_tlb_kernel_page(vaddr); | ||
| 28 | } | ||
| 29 | |||
| 30 | static inline pte_t get_fixmap_pte(unsigned long vaddr) | ||
| 31 | { | ||
| 32 | unsigned long idx = __virt_to_fix(vaddr); | ||
| 33 | return *(fixmap_page_table + idx); | ||
| 34 | } | ||
| 35 | |||
| 21 | void *kmap(struct page *page) | 36 | void *kmap(struct page *page) |
| 22 | { | 37 | { |
| 23 | might_sleep(); | 38 | might_sleep(); |
| @@ -63,20 +78,20 @@ void *kmap_atomic(struct page *page) | |||
| 63 | type = kmap_atomic_idx_push(); | 78 | type = kmap_atomic_idx_push(); |
| 64 | 79 | ||
| 65 | idx = type + KM_TYPE_NR * smp_processor_id(); | 80 | idx = type + KM_TYPE_NR * smp_processor_id(); |
| 66 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 81 | vaddr = __fix_to_virt(idx); |
| 67 | #ifdef CONFIG_DEBUG_HIGHMEM | 82 | #ifdef CONFIG_DEBUG_HIGHMEM |
| 68 | /* | 83 | /* |
| 69 | * With debugging enabled, kunmap_atomic forces that entry to 0. | 84 | * With debugging enabled, kunmap_atomic forces that entry to 0. |
| 70 | * Make sure it was indeed properly unmapped. | 85 | * Make sure it was indeed properly unmapped. |
| 71 | */ | 86 | */ |
| 72 | BUG_ON(!pte_none(get_top_pte(vaddr))); | 87 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); |
| 73 | #endif | 88 | #endif |
| 74 | /* | 89 | /* |
| 75 | * When debugging is off, kunmap_atomic leaves the previous mapping | 90 | * When debugging is off, kunmap_atomic leaves the previous mapping |
| 76 | * in place, so the contained TLB flush ensures the TLB is updated | 91 | * in place, so the contained TLB flush ensures the TLB is updated |
| 77 | * with the new mapping. | 92 | * with the new mapping. |
| 78 | */ | 93 | */ |
| 79 | set_top_pte(vaddr, mk_pte(page, kmap_prot)); | 94 | set_fixmap_pte(idx, mk_pte(page, kmap_prot)); |
| 80 | 95 | ||
| 81 | return (void *)vaddr; | 96 | return (void *)vaddr; |
| 82 | } | 97 | } |
| @@ -94,8 +109,8 @@ void __kunmap_atomic(void *kvaddr) | |||
| 94 | if (cache_is_vivt()) | 109 | if (cache_is_vivt()) |
| 95 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); | 110 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); |
| 96 | #ifdef CONFIG_DEBUG_HIGHMEM | 111 | #ifdef CONFIG_DEBUG_HIGHMEM |
| 97 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | 112 | BUG_ON(vaddr != __fix_to_virt(idx)); |
| 98 | set_top_pte(vaddr, __pte(0)); | 113 | set_fixmap_pte(idx, __pte(0)); |
| 99 | #else | 114 | #else |
| 100 | (void) idx; /* to kill a warning */ | 115 | (void) idx; /* to kill a warning */ |
| 101 | #endif | 116 | #endif |
| @@ -117,11 +132,11 @@ void *kmap_atomic_pfn(unsigned long pfn) | |||
| 117 | 132 | ||
| 118 | type = kmap_atomic_idx_push(); | 133 | type = kmap_atomic_idx_push(); |
| 119 | idx = type + KM_TYPE_NR * smp_processor_id(); | 134 | idx = type + KM_TYPE_NR * smp_processor_id(); |
| 120 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 135 | vaddr = __fix_to_virt(idx); |
| 121 | #ifdef CONFIG_DEBUG_HIGHMEM | 136 | #ifdef CONFIG_DEBUG_HIGHMEM |
| 122 | BUG_ON(!pte_none(get_top_pte(vaddr))); | 137 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); |
| 123 | #endif | 138 | #endif |
| 124 | set_top_pte(vaddr, pfn_pte(pfn, kmap_prot)); | 139 | set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); |
| 125 | 140 | ||
| 126 | return (void *)vaddr; | 141 | return (void *)vaddr; |
| 127 | } | 142 | } |
| @@ -133,5 +148,5 @@ struct page *kmap_atomic_to_page(const void *ptr) | |||
| 133 | if (vaddr < FIXADDR_START) | 148 | if (vaddr < FIXADDR_START) |
| 134 | return virt_to_page(ptr); | 149 | return virt_to_page(ptr); |
| 135 | 150 | ||
| 136 | return pte_page(get_top_pte(vaddr)); | 151 | return pte_page(get_fixmap_pte(vaddr)); |
| 137 | } | 152 | } |
