diff options
author | venkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com> | 2008-03-18 20:00:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-24 17:40:47 -0400 |
commit | e045fb2a988a9a1964059b0d33dbaf18d12f925f (patch) | |
tree | 61dbd03abd83dcf6d5195fa6463ea96e125784f6 /drivers/char/mem.c | |
parent | e2beb3eae627211b67e456c53f946cede2ac10d7 (diff) |
x86: PAT avoid aliasing in /dev/mem read/write
Add xlate and unxlate around /dev/mem read/write. This sets up the mapping
that can be used for /dev/mem read and write without aliasing worries.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r-- | drivers/char/mem.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 964ff3b1cff4..83495885ada0 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -134,6 +134,10 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) | |||
134 | } | 134 | } |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr) | ||
138 | { | ||
139 | } | ||
140 | |||
137 | /* | 141 | /* |
138 | * This funcion reads the *physical* memory. The f_pos points directly to the | 142 | * This funcion reads the *physical* memory. The f_pos points directly to the |
139 | * memory location. | 143 | * memory location. |
@@ -176,17 +180,25 @@ static ssize_t read_mem(struct file * file, char __user * buf, | |||
176 | 180 | ||
177 | sz = min_t(unsigned long, sz, count); | 181 | sz = min_t(unsigned long, sz, count); |
178 | 182 | ||
183 | if (!range_is_allowed(p >> PAGE_SHIFT, count)) | ||
184 | return -EPERM; | ||
185 | |||
179 | /* | 186 | /* |
180 | * On ia64 if a page has been mapped somewhere as | 187 | * On ia64 if a page has been mapped somewhere as |
181 | * uncached, then it must also be accessed uncached | 188 | * uncached, then it must also be accessed uncached |
182 | * by the kernel or data corruption may occur | 189 | * by the kernel or data corruption may occur |
183 | */ | 190 | */ |
184 | ptr = xlate_dev_mem_ptr(p); | 191 | ptr = xlate_dev_mem_ptr(p); |
192 | if (!ptr) | ||
193 | return -EFAULT; | ||
185 | 194 | ||
186 | if (!range_is_allowed(p >> PAGE_SHIFT, count)) | 195 | if (copy_to_user(buf, ptr, sz)) { |
187 | return -EPERM; | 196 | unxlate_dev_mem_ptr(p, ptr); |
188 | if (copy_to_user(buf, ptr, sz)) | ||
189 | return -EFAULT; | 197 | return -EFAULT; |
198 | } | ||
199 | |||
200 | unxlate_dev_mem_ptr(p, ptr); | ||
201 | |||
190 | buf += sz; | 202 | buf += sz; |
191 | p += sz; | 203 | p += sz; |
192 | count -= sz; | 204 | count -= sz; |
@@ -235,22 +247,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
235 | 247 | ||
236 | sz = min_t(unsigned long, sz, count); | 248 | sz = min_t(unsigned long, sz, count); |
237 | 249 | ||
250 | if (!range_is_allowed(p >> PAGE_SHIFT, sz)) | ||
251 | return -EPERM; | ||
252 | |||
238 | /* | 253 | /* |
239 | * On ia64 if a page has been mapped somewhere as | 254 | * On ia64 if a page has been mapped somewhere as |
240 | * uncached, then it must also be accessed uncached | 255 | * uncached, then it must also be accessed uncached |
241 | * by the kernel or data corruption may occur | 256 | * by the kernel or data corruption may occur |
242 | */ | 257 | */ |
243 | ptr = xlate_dev_mem_ptr(p); | 258 | ptr = xlate_dev_mem_ptr(p); |
259 | if (!ptr) { | ||
260 | if (written) | ||
261 | break; | ||
262 | return -EFAULT; | ||
263 | } | ||
244 | 264 | ||
245 | if (!range_is_allowed(p >> PAGE_SHIFT, sz)) | ||
246 | return -EPERM; | ||
247 | copied = copy_from_user(ptr, buf, sz); | 265 | copied = copy_from_user(ptr, buf, sz); |
248 | if (copied) { | 266 | if (copied) { |
249 | written += sz - copied; | 267 | written += sz - copied; |
268 | unxlate_dev_mem_ptr(p, ptr); | ||
250 | if (written) | 269 | if (written) |
251 | break; | 270 | break; |
252 | return -EFAULT; | 271 | return -EFAULT; |
253 | } | 272 | } |
273 | |||
274 | unxlate_dev_mem_ptr(p, ptr); | ||
275 | |||
254 | buf += sz; | 276 | buf += sz; |
255 | p += sz; | 277 | p += sz; |
256 | count -= sz; | 278 | count -= sz; |