diff options
| -rw-r--r-- | arch/sh/mm/cache.c | 66 | 
1 files changed, 13 insertions, 53 deletions
| diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 997c7e42b1e1..e9415d3ea94a 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c | |||
| @@ -46,18 +46,6 @@ static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info, | |||
| 46 | preempt_enable(); | 46 | preempt_enable(); | 
| 47 | } | 47 | } | 
| 48 | 48 | ||
| 49 | /* | ||
| 50 | * copy_to_user_page | ||
| 51 | * @vma: vm_area_struct holding the pages | ||
| 52 | * @page: struct page | ||
| 53 | * @vaddr: user space address | ||
| 54 | * @dst: address of page in kernel space (possibly from kmap) | ||
| 55 | * @src: source address in kernel logical memory | ||
| 56 | * @len: length of data in bytes (may be less than PAGE_SIZE) | ||
| 57 | * | ||
| 58 | * Copy data into the address space of a process other than the current | ||
| 59 | * process (eg for ptrace). | ||
| 60 | */ | ||
| 61 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | 49 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | 
| 62 | unsigned long vaddr, void *dst, const void *src, | 50 | unsigned long vaddr, void *dst, const void *src, | 
| 63 | unsigned long len) | 51 | unsigned long len) | 
| @@ -93,49 +81,28 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, | |||
| 93 | } | 81 | } | 
| 94 | } | 82 | } | 
| 95 | 83 | ||
| 96 | /* | ||
| 97 | * copy_user_highpage | ||
| 98 | * @to: destination page | ||
| 99 | * @from: source page | ||
| 100 | * @vaddr: address of pages in user address space | ||
| 101 | * @vma: vm_area_struct holding the pages | ||
| 102 | * | ||
| 103 | * This is used in COW implementation to copy data from page @from to | ||
| 104 | * page @to. @from was previousl mapped at @vaddr, and @to will be. | ||
| 105 | * As this is used only in the COW implementation, this means that the | ||
| 106 | * source is unmodified, and so we don't have to worry about cache | ||
| 107 | * aliasing on that side. | ||
| 108 | */ | ||
| 109 | #ifdef CONFIG_HIGHMEM | ||
| 110 | /* | ||
| 111 | * If we ever have a real highmem system, this code will need fixing | ||
| 112 | * (as will clear_user/clear_user_highmem), because the kmap potentitally | ||
| 113 | * creates another alias risk. | ||
| 114 | */ | ||
| 115 | #error This code is broken with real HIGHMEM | ||
| 116 | #endif | ||
| 117 | void copy_user_highpage(struct page *to, struct page *from, | 84 | void copy_user_highpage(struct page *to, struct page *from, | 
| 118 | unsigned long vaddr, struct vm_area_struct *vma) | 85 | unsigned long vaddr, struct vm_area_struct *vma) | 
| 119 | { | 86 | { | 
| 120 | void *vfrom, *vto; | 87 | void *vfrom, *vto; | 
| 121 | 88 | ||
| 122 | vto = kmap_atomic(to, KM_USER1); | 89 | vto = kmap_atomic(to, KM_USER1); | 
| 123 | vfrom = kmap_atomic(from, KM_USER0); | ||
| 124 | |||
| 125 | if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) | ||
| 126 | __flush_invalidate_region(vto, PAGE_SIZE); | ||
| 127 | 90 | ||
| 128 | if (boot_cpu_data.dcache.n_aliases && page_mapped(from) && | 91 | if (boot_cpu_data.dcache.n_aliases && page_mapped(from) && | 
| 129 | !test_bit(PG_dcache_dirty, &from->flags)) { | 92 | !test_bit(PG_dcache_dirty, &from->flags)) { | 
| 130 | void *vto_coloured = kmap_coherent(to, vaddr); | 93 | vfrom = kmap_coherent(from, vaddr); | 
| 131 | copy_page(vto_coloured, vfrom); | ||
| 132 | kunmap_coherent(vto_coloured); | ||
| 133 | } else | ||
| 134 | copy_page(vto, vfrom); | 94 | copy_page(vto, vfrom); | 
| 95 | kunmap_coherent(vfrom); | ||
| 96 | } else { | ||
| 97 | vfrom = kmap_atomic(from, KM_USER0); | ||
| 98 | copy_page(vto, vfrom); | ||
| 99 | kunmap_atomic(vfrom, KM_USER0); | ||
| 100 | } | ||
| 135 | 101 | ||
| 136 | kunmap_atomic(vfrom, KM_USER0); | 102 | if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) | 
| 137 | kunmap_atomic(vto, KM_USER1); | 103 | __flush_purge_region(vto, PAGE_SIZE); | 
| 138 | 104 | ||
| 105 | kunmap_atomic(vto, KM_USER1); | ||
| 139 | /* Make sure this page is cleared on other CPU's too before using it */ | 106 | /* Make sure this page is cleared on other CPU's too before using it */ | 
| 140 | smp_wmb(); | 107 | smp_wmb(); | 
| 141 | } | 108 | } | 
| @@ -145,17 +112,10 @@ void clear_user_highpage(struct page *page, unsigned long vaddr) | |||
| 145 | { | 112 | { | 
| 146 | void *kaddr = kmap_atomic(page, KM_USER0); | 113 | void *kaddr = kmap_atomic(page, KM_USER0); | 
| 147 | 114 | ||
| 148 | if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK)) { | 115 | clear_page(kaddr); | 
| 149 | void *vto; | ||
| 150 | 116 | ||
| 151 | /* Kernel alias may have modified data in the cache. */ | 117 | if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK)) | 
| 152 | __flush_invalidate_region(kaddr, PAGE_SIZE); | 118 | __flush_purge_region(kaddr, PAGE_SIZE); | 
| 153 | |||
| 154 | vto = kmap_coherent(page, vaddr); | ||
| 155 | clear_page(vto); | ||
| 156 | kunmap_coherent(vto); | ||
| 157 | } else | ||
| 158 | clear_page(kaddr); | ||
| 159 | 119 | ||
| 160 | kunmap_atomic(kaddr, KM_USER0); | 120 | kunmap_atomic(kaddr, KM_USER0); | 
| 161 | } | 121 | } | 
