aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2009-04-25 05:25:34 -0400
committerRalf Baechle <ralf@linux-mips.org>2009-05-14 08:50:29 -0400
commitbb86bf28aec6d0a207ae09f38a43e94133d4d6db (patch)
tree34bd8f653eb10dc4eb82aa8ef2576475346070e1
parent0b54352600b820a6d25f151cbd8975ed9b2aeb09 (diff)
MIPS: Fix highmem.
Commit 351336929ccf222ae38ff0cb7a8dd5fd5c6236a0 (kernel.org) rsp. b3594a089f1c17ff919f8f78505c3f20e1f6f8ce (linux-mips.org): > From: Chris Dearman <chris@mips.com> > Date: Wed, 19 Sep 2007 00:58:24 +0100 > Subject: [PATCH] [MIPS] Allow setting of the cache attribute at run time. > > Slightly tacky, but there is a precedent in the sparc archirecture code. introduces the variable _page_cachable_default, which defaults to zero and. is used to create the prototype PTE for __kmap_atomic in arch/mips/mm/init.c:kmap_init before initialization in arch/mips/mm/c-r4k.c:coherency_setup, so the default value of 0 will be used as the CCA of kmap atomic pages which on many processors is not a defined CCA value and may result in writes to kmap_atomic pages getting corrupted. Debugged by Jon Fraser (jfraser@broadcom.com). Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/fixmap.h3
-rw-r--r--arch/mips/include/asm/highmem.h6
-rw-r--r--arch/mips/mm/highmem.c25
-rw-r--r--arch/mips/mm/init.c26
4 files changed, 26 insertions, 34 deletions
diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h
index 9cc8522a394f..0f5caa1307f1 100644
--- a/arch/mips/include/asm/fixmap.h
+++ b/arch/mips/include/asm/fixmap.h
@@ -108,6 +108,9 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
108 return __virt_to_fix(vaddr); 108 return __virt_to_fix(vaddr);
109} 109}
110 110
111#define kmap_get_fixmap_pte(vaddr) \
112 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
113
111/* 114/*
112 * Called from pgtable_init() 115 * Called from pgtable_init()
113 */ 116 */
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index 4374ab2adc75..25adfb02923d 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -30,8 +30,6 @@
30/* declarations for highmem.c */ 30/* declarations for highmem.c */
31extern unsigned long highstart_pfn, highend_pfn; 31extern unsigned long highstart_pfn, highend_pfn;
32 32
33extern pte_t *kmap_pte;
34extern pgprot_t kmap_prot;
35extern pte_t *pkmap_page_table; 33extern pte_t *pkmap_page_table;
36 34
37/* 35/*
@@ -62,6 +60,10 @@ extern struct page *__kmap_atomic_to_page(void *ptr);
62 60
63#define flush_cache_kmaps() flush_cache_all() 61#define flush_cache_kmaps() flush_cache_all()
64 62
63extern void kmap_init(void);
64
65#define kmap_prot PAGE_KERNEL
66
65#endif /* __KERNEL__ */ 67#endif /* __KERNEL__ */
66 68
67#endif /* _ASM_HIGHMEM_H */ 69#endif /* _ASM_HIGHMEM_H */
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 4481656d1065..2b1309b2580a 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -1,7 +1,12 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/highmem.h> 2#include <linux/highmem.h>
3#include <asm/fixmap.h>
3#include <asm/tlbflush.h> 4#include <asm/tlbflush.h>
4 5
6static pte_t *kmap_pte;
7
8unsigned long highstart_pfn, highend_pfn;
9
5void *__kmap(struct page *page) 10void *__kmap(struct page *page)
6{ 11{
7 void *addr; 12 void *addr;
@@ -14,6 +19,7 @@ void *__kmap(struct page *page)
14 19
15 return addr; 20 return addr;
16} 21}
22EXPORT_SYMBOL(__kmap);
17 23
18void __kunmap(struct page *page) 24void __kunmap(struct page *page)
19{ 25{
@@ -22,6 +28,7 @@ void __kunmap(struct page *page)
22 return; 28 return;
23 kunmap_high(page); 29 kunmap_high(page);
24} 30}
31EXPORT_SYMBOL(__kunmap);
25 32
26/* 33/*
27 * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because 34 * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
@@ -48,11 +55,12 @@ void *__kmap_atomic(struct page *page, enum km_type type)
48#ifdef CONFIG_DEBUG_HIGHMEM 55#ifdef CONFIG_DEBUG_HIGHMEM
49 BUG_ON(!pte_none(*(kmap_pte - idx))); 56 BUG_ON(!pte_none(*(kmap_pte - idx)));
50#endif 57#endif
51 set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); 58 set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
52 local_flush_tlb_one((unsigned long)vaddr); 59 local_flush_tlb_one((unsigned long)vaddr);
53 60
54 return (void*) vaddr; 61 return (void*) vaddr;
55} 62}
63EXPORT_SYMBOL(__kmap_atomic);
56 64
57void __kunmap_atomic(void *kvaddr, enum km_type type) 65void __kunmap_atomic(void *kvaddr, enum km_type type)
58{ 66{
@@ -77,6 +85,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
77 85
78 pagefault_enable(); 86 pagefault_enable();
79} 87}
88EXPORT_SYMBOL(__kunmap_atomic);
80 89
81/* 90/*
82 * This is the same as kmap_atomic() but can map memory that doesn't 91 * This is the same as kmap_atomic() but can map memory that doesn't
@@ -92,7 +101,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
92 debug_kmap_atomic(type); 101 debug_kmap_atomic(type);
93 idx = type + KM_TYPE_NR*smp_processor_id(); 102 idx = type + KM_TYPE_NR*smp_processor_id();
94 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 103 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
95 set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); 104 set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
96 flush_tlb_one(vaddr); 105 flush_tlb_one(vaddr);
97 106
98 return (void*) vaddr; 107 return (void*) vaddr;
@@ -111,7 +120,11 @@ struct page *__kmap_atomic_to_page(void *ptr)
111 return pte_page(*pte); 120 return pte_page(*pte);
112} 121}
113 122
114EXPORT_SYMBOL(__kmap); 123void __init kmap_init(void)
115EXPORT_SYMBOL(__kunmap); 124{
116EXPORT_SYMBOL(__kmap_atomic); 125 unsigned long kmap_vstart;
117EXPORT_SYMBOL(__kunmap_atomic); 126
127 /* cache the first kmap pte */
128 kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
129 kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
130}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index d9348946a19e..c5511294a9ee 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -104,14 +104,6 @@ unsigned long setup_zero_pages(void)
104 return 1UL << order; 104 return 1UL << order;
105} 105}
106 106
107/*
108 * These are almost like kmap_atomic / kunmap_atmic except they take an
109 * additional address argument as the hint.
110 */
111
112#define kmap_get_fixmap_pte(vaddr) \
113 pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
114
115#ifdef CONFIG_MIPS_MT_SMTC 107#ifdef CONFIG_MIPS_MT_SMTC
116static pte_t *kmap_coherent_pte; 108static pte_t *kmap_coherent_pte;
117static void __init kmap_coherent_init(void) 109static void __init kmap_coherent_init(void)
@@ -264,24 +256,6 @@ void copy_from_user_page(struct vm_area_struct *vma,
264 } 256 }
265} 257}
266 258
267#ifdef CONFIG_HIGHMEM
268unsigned long highstart_pfn, highend_pfn;
269
270pte_t *kmap_pte;
271pgprot_t kmap_prot;
272
273static void __init kmap_init(void)
274{
275 unsigned long kmap_vstart;
276
277 /* cache the first kmap pte */
278 kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
279 kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
280
281 kmap_prot = PAGE_KERNEL;
282}
283#endif /* CONFIG_HIGHMEM */
284
285void __init fixrange_init(unsigned long start, unsigned long end, 259void __init fixrange_init(unsigned long start, unsigned long end,
286 pgd_t *pgd_base) 260 pgd_t *pgd_base)
287{ 261{