aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/highmem.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/highmem.h')
-rw-r--r--include/linux/highmem.h52
1 files changed, 30 insertions, 22 deletions
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 1fcb0033179e..7dcbc82f3b7b 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -68,8 +68,6 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
68 void *addr = kmap_atomic(page, KM_USER0); 68 void *addr = kmap_atomic(page, KM_USER0);
69 clear_user_page(addr, vaddr, page); 69 clear_user_page(addr, vaddr, page);
70 kunmap_atomic(addr, KM_USER0); 70 kunmap_atomic(addr, KM_USER0);
71 /* Make sure this page is cleared on other CPU's too before using it */
72 smp_wmb();
73} 71}
74 72
75#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 73#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
@@ -124,28 +122,40 @@ static inline void clear_highpage(struct page *page)
124 kunmap_atomic(kaddr, KM_USER0); 122 kunmap_atomic(kaddr, KM_USER0);
125} 123}
126 124
127/* 125static inline void zero_user_segments(struct page *page,
128 * Same but also flushes aliased cache contents to RAM. 126 unsigned start1, unsigned end1,
129 * 127 unsigned start2, unsigned end2)
130 * This must be a macro because KM_USER0 and friends aren't defined if 128{
131 * !CONFIG_HIGHMEM 129 void *kaddr = kmap_atomic(page, KM_USER0);
132 */ 130
133#define zero_user_page(page, offset, size, km_type) \ 131 BUG_ON(end1 > PAGE_SIZE || end2 > PAGE_SIZE);
134 do { \ 132
135 void *kaddr; \ 133 if (end1 > start1)
136 \ 134 memset(kaddr + start1, 0, end1 - start1);
137 BUG_ON((offset) + (size) > PAGE_SIZE); \ 135
138 \ 136 if (end2 > start2)
139 kaddr = kmap_atomic(page, km_type); \ 137 memset(kaddr + start2, 0, end2 - start2);
140 memset((char *)kaddr + (offset), 0, (size)); \ 138
141 flush_dcache_page(page); \ 139 kunmap_atomic(kaddr, KM_USER0);
142 kunmap_atomic(kaddr, (km_type)); \ 140 flush_dcache_page(page);
143 } while (0) 141}
142
143static inline void zero_user_segment(struct page *page,
144 unsigned start, unsigned end)
145{
146 zero_user_segments(page, start, end, 0, 0);
147}
148
149static inline void zero_user(struct page *page,
150 unsigned start, unsigned size)
151{
152 zero_user_segments(page, start, start + size, 0, 0);
153}
144 154
145static inline void __deprecated memclear_highpage_flush(struct page *page, 155static inline void __deprecated memclear_highpage_flush(struct page *page,
146 unsigned int offset, unsigned int size) 156 unsigned int offset, unsigned int size)
147{ 157{
148 zero_user_page(page, offset, size, KM_USER0); 158 zero_user(page, offset, size);
149} 159}
150 160
151#ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE 161#ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
@@ -160,8 +170,6 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
160 copy_user_page(vto, vfrom, vaddr, to); 170 copy_user_page(vto, vfrom, vaddr, to);
161 kunmap_atomic(vfrom, KM_USER0); 171 kunmap_atomic(vfrom, KM_USER0);
162 kunmap_atomic(vto, KM_USER1); 172 kunmap_atomic(vto, KM_USER1);
163 /* Make sure this page is cleared on other CPU's too before using it */
164 smp_wmb();
165} 173}
166 174
167#endif 175#endif