Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+26 -34
+3
arch/mips/include/asm/fixmap.h
··· 108 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 115 * Called from pgtable_init() 113 116 */
+4 -2
arch/mips/include/asm/highmem.h
··· 30 30 /* declarations for highmem.c */ 31 31 extern unsigned long highstart_pfn, highend_pfn; 32 32 33 - extern pte_t *kmap_pte; 34 - extern pgprot_t kmap_prot; 35 33 extern pte_t *pkmap_page_table; 36 34 37 35 /* ··· 59 61 #define kmap_atomic_to_page __kmap_atomic_to_page 60 62 61 63 #define flush_cache_kmaps() flush_cache_all() 64 + 65 + extern void kmap_init(void); 66 + 67 + #define kmap_prot PAGE_KERNEL 62 68 63 69 #endif /* __KERNEL__ */ 64 70
+19 -6
arch/mips/mm/highmem.c
··· 1 1 #include <linux/module.h> 2 2 #include <linux/highmem.h> 3 + #include <asm/fixmap.h> 3 4 #include <asm/tlbflush.h> 5 + 6 + static pte_t *kmap_pte; 7 + 8 + unsigned long highstart_pfn, highend_pfn; 4 9 5 10 void *__kmap(struct page *page) 6 11 { ··· 19 14 20 15 return addr; 21 16 } 17 + EXPORT_SYMBOL(__kmap); 22 18 23 19 void __kunmap(struct page *page) 24 20 { ··· 28 22 return; 29 23 kunmap_high(page); 30 24 } 25 + EXPORT_SYMBOL(__kunmap); 31 26 32 27 /* 33 28 * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because ··· 55 48 #ifdef CONFIG_DEBUG_HIGHMEM 56 49 BUG_ON(!pte_none(*(kmap_pte - idx))); 57 50 #endif 58 - set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); 51 + set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL)); 59 52 local_flush_tlb_one((unsigned long)vaddr); 60 53 61 54 return (void*) vaddr; 62 55 } 56 + EXPORT_SYMBOL(__kmap_atomic); 63 57 64 58 void __kunmap_atomic(void *kvaddr, enum km_type type) 65 59 { ··· 85 77 86 78 pagefault_enable(); 87 79 } 80 + EXPORT_SYMBOL(__kunmap_atomic); 88 81 89 82 /* 90 83 * This is the same as kmap_atomic() but can map memory that doesn't ··· 101 92 debug_kmap_atomic(type); 102 93 idx = type + KM_TYPE_NR*smp_processor_id(); 103 94 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 104 - set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); 95 + set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL)); 105 96 flush_tlb_one(vaddr); 106 97 107 98 return (void*) vaddr; ··· 120 111 return pte_page(*pte); 121 112 } 122 113 123 - EXPORT_SYMBOL(__kmap); 124 - EXPORT_SYMBOL(__kunmap); 125 - EXPORT_SYMBOL(__kmap_atomic); 126 - EXPORT_SYMBOL(__kunmap_atomic); 114 + void __init kmap_init(void) 115 + { 116 + unsigned long kmap_vstart; 117 + 118 + /* cache the first kmap pte */ 119 + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); 120 + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); 121 + }
-26
arch/mips/mm/init.c
··· 104 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 107 #ifdef CONFIG_MIPS_MT_SMTC 116 108 static pte_t *kmap_coherent_pte; 117 109 static void __init kmap_coherent_init(void) ··· 255 263 SetPageDcacheDirty(page); 256 264 } 257 265 } 258 - 259 - #ifdef CONFIG_HIGHMEM 260 - unsigned long highstart_pfn, highend_pfn; 261 - 262 - pte_t *kmap_pte; 263 - pgprot_t kmap_prot; 264 - 265 - static void __init kmap_init(void) 266 - { 267 - unsigned long kmap_vstart; 268 - 269 - /* cache the first kmap pte */ 270 - kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); 271 - kmap_pte = kmap_get_fixmap_pte(kmap_vstart); 272 - 273 - kmap_prot = PAGE_KERNEL; 274 - } 275 - #endif /* CONFIG_HIGHMEM */ 276 266 277 267 void __init fixrange_init(unsigned long start, unsigned long end, 278 268 pgd_t *pgd_base)