aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/Kconfig.debug11
-rw-r--r--arch/x86/mm/init_32.c19
-rw-r--r--arch/x86/mm/init_64.c20
-rw-r--r--arch/x86/mm/ioremap.c29
-rw-r--r--arch/x86/mm/pat.c175
-rw-r--r--drivers/char/mem.c133
-rw-r--r--include/asm-generic/iomap.h4
-rw-r--r--include/asm-x86/io.h8
-rw-r--r--include/asm-x86/io_32.h6
-rw-r--r--include/asm-x86/io_64.h6
-rw-r--r--include/asm-x86/page.h1
-rw-r--r--include/asm-x86/pgtable.h9
12 files changed, 363 insertions, 58 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 610aaecc19f8..239fd9fba0a5 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -5,6 +5,17 @@ config TRACE_IRQFLAGS_SUPPORT
5 5
6source "lib/Kconfig.debug" 6source "lib/Kconfig.debug"
7 7
8config NONPROMISC_DEVMEM
9 bool "Disable promiscuous /dev/mem"
10 help
11 The /dev/mem file by default only allows userspace access to PCI
12 space and the BIOS code and data regions. This is sufficient for
13 dosemu and X and all common users of /dev/mem. With this config
14 option, you allow userspace access to all of memory, including
15 kernel and userspace memory. Accidental access to this is
16 obviously disasterous, but specific access can be used by people
17 debugging the kernel.
18
8config EARLY_PRINTK 19config EARLY_PRINTK
9 bool "Early printk" if EMBEDDED 20 bool "Early printk" if EMBEDDED
10 default y 21 default y
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 08aa1878fad4..baf7c4f643c8 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -227,6 +227,25 @@ static inline int page_kills_ppro(unsigned long pagenr)
227 return 0; 227 return 0;
228} 228}
229 229
230/*
231 * devmem_is_allowed() checks to see if /dev/mem access to a certain address
232 * is valid. The argument is a physical page number.
233 *
234 *
235 * On x86, access has to be given to the first megabyte of ram because that area
236 * contains bios code and data regions used by X and dosemu and similar apps.
237 * Access has to be given to non-kernel-ram areas as well, these contain the PCI
238 * mmio resources as well as potential bios/acpi data regions.
239 */
240int devmem_is_allowed(unsigned long pagenr)
241{
242 if (pagenr <= 256)
243 return 1;
244 if (!page_is_ram(pagenr))
245 return 1;
246 return 0;
247}
248
230#ifdef CONFIG_HIGHMEM 249#ifdef CONFIG_HIGHMEM
231pte_t *kmap_pte; 250pte_t *kmap_pte;
232pgprot_t kmap_prot; 251pgprot_t kmap_prot;
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index b798e7b92b17..0cca62663037 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -663,6 +663,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
663 663
664#endif /* CONFIG_MEMORY_HOTPLUG */ 664#endif /* CONFIG_MEMORY_HOTPLUG */
665 665
666/*
667 * devmem_is_allowed() checks to see if /dev/mem access to a certain address
668 * is valid. The argument is a physical page number.
669 *
670 *
671 * On x86, access has to be given to the first megabyte of ram because that area
672 * contains bios code and data regions used by X and dosemu and similar apps.
673 * Access has to be given to non-kernel-ram areas as well, these contain the PCI
674 * mmio resources as well as potential bios/acpi data regions.
675 */
676int devmem_is_allowed(unsigned long pagenr)
677{
678 if (pagenr <= 256)
679 return 1;
680 if (!page_is_ram(pagenr))
681 return 1;
682 return 0;
683}
684
685
666static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, 686static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
667 kcore_modules, kcore_vsyscall; 687 kcore_modules, kcore_vsyscall;
668 688
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 36a3f7ded626..d176b23110cc 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -336,6 +336,35 @@ void iounmap(volatile void __iomem *addr)
336} 336}
337EXPORT_SYMBOL(iounmap); 337EXPORT_SYMBOL(iounmap);
338 338
339/*
340 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
341 * access
342 */
343void *xlate_dev_mem_ptr(unsigned long phys)
344{
345 void *addr;
346 unsigned long start = phys & PAGE_MASK;
347
348 /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
349 if (page_is_ram(start >> PAGE_SHIFT))
350 return __va(phys);
351
352 addr = (void *)ioremap(start, PAGE_SIZE);
353 if (addr)
354 addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
355
356 return addr;
357}
358
359void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
360{
361 if (page_is_ram(phys >> PAGE_SHIFT))
362 return;
363
364 iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
365 return;
366}
367
339#ifdef CONFIG_X86_32 368#ifdef CONFIG_X86_32
340 369
341int __initdata early_ioremap_debug; 370int __initdata early_ioremap_debug;
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 72c0f6097402..ef8b64b89c7d 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -11,6 +11,7 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/gfp.h> 12#include <linux/gfp.h>
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/bootmem.h>
14 15
15#include <asm/msr.h> 16#include <asm/msr.h>
16#include <asm/tlbflush.h> 17#include <asm/tlbflush.h>
@@ -21,6 +22,7 @@
21#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
22#include <asm/fcntl.h> 23#include <asm/fcntl.h>
23#include <asm/mtrr.h> 24#include <asm/mtrr.h>
25#include <asm/io.h>
24 26
25int pat_wc_enabled = 1; 27int pat_wc_enabled = 1;
26 28
@@ -190,6 +192,21 @@ static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
190 return 0; 192 return 0;
191} 193}
192 194
195/*
196 * req_type typically has one of the:
197 * - _PAGE_CACHE_WB
198 * - _PAGE_CACHE_WC
199 * - _PAGE_CACHE_UC_MINUS
200 * - _PAGE_CACHE_UC
201 *
202 * req_type will have a special case value '-1', when requester want to inherit
203 * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
204 *
205 * If ret_type is NULL, function will return an error if it cannot reserve the
206 * region with req_type. If ret_type is non-null, function will return
207 * available type in ret_type in case of no error. In case of any error
208 * it will return a negative return value.
209 */
193int reserve_memtype(u64 start, u64 end, unsigned long req_type, 210int reserve_memtype(u64 start, u64 end, unsigned long req_type,
194 unsigned long *ret_type) 211 unsigned long *ret_type)
195{ 212{
@@ -200,9 +217,14 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
200 217
201 /* Only track when pat_wc_enabled */ 218 /* Only track when pat_wc_enabled */
202 if (!pat_wc_enabled) { 219 if (!pat_wc_enabled) {
203 if (ret_type) 220 /* This is identical to page table setting without PAT */
204 *ret_type = req_type; 221 if (ret_type) {
205 222 if (req_type == -1) {
223 *ret_type = _PAGE_CACHE_WB;
224 } else {
225 *ret_type = req_type;
226 }
227 }
206 return 0; 228 return 0;
207 } 229 }
208 230
@@ -214,8 +236,29 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
214 return 0; 236 return 0;
215 } 237 }
216 238
217 req_type &= _PAGE_CACHE_MASK; 239 if (req_type == -1) {
218 err = pat_x_mtrr_type(start, end, req_type, &actual_type); 240 /*
241 * Special case where caller wants to inherit from mtrr or
242 * existing pat mapping, defaulting to UC_MINUS in case of
243 * no match.
244 */
245 u8 mtrr_type = mtrr_type_lookup(start, end);
246 if (mtrr_type == 0xFE) { /* MTRR match error */
247 err = -1;
248 }
249
250 if (mtrr_type == MTRR_TYPE_WRBACK) {
251 req_type = _PAGE_CACHE_WB;
252 actual_type = _PAGE_CACHE_WB;
253 } else {
254 req_type = _PAGE_CACHE_UC_MINUS;
255 actual_type = _PAGE_CACHE_UC_MINUS;
256 }
257 } else {
258 req_type &= _PAGE_CACHE_MASK;
259 err = pat_x_mtrr_type(start, end, req_type, &actual_type);
260 }
261
219 if (err) { 262 if (err) {
220 if (ret_type) 263 if (ret_type)
221 *ret_type = actual_type; 264 *ret_type = actual_type;
@@ -241,7 +284,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
241 struct memtype *saved_ptr; 284 struct memtype *saved_ptr;
242 285
243 if (parse->start >= end) { 286 if (parse->start >= end) {
244 printk("New Entry\n"); 287 pr_debug("New Entry\n");
245 list_add(&new_entry->nd, parse->nd.prev); 288 list_add(&new_entry->nd, parse->nd.prev);
246 new_entry = NULL; 289 new_entry = NULL;
247 break; 290 break;
@@ -343,7 +386,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
343 break; 386 break;
344 } 387 }
345 388
346 printk("Overlap at 0x%Lx-0x%Lx\n", 389 printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
347 saved_ptr->start, saved_ptr->end); 390 saved_ptr->start, saved_ptr->end);
348 /* No conflict. Go ahead and add this new entry */ 391 /* No conflict. Go ahead and add this new entry */
349 list_add(&new_entry->nd, &saved_ptr->nd); 392 list_add(&new_entry->nd, &saved_ptr->nd);
@@ -353,7 +396,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
353 } 396 }
354 397
355 if (err) { 398 if (err) {
356 printk( 399 printk(KERN_INFO
357 "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n", 400 "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
358 start, end, cattr_name(new_entry->type), 401 start, end, cattr_name(new_entry->type),
359 cattr_name(req_type)); 402 cattr_name(req_type));
@@ -365,16 +408,16 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
365 if (new_entry) { 408 if (new_entry) {
366 /* No conflict. Not yet added to the list. Add to the tail */ 409 /* No conflict. Not yet added to the list. Add to the tail */
367 list_add_tail(&new_entry->nd, &memtype_list); 410 list_add_tail(&new_entry->nd, &memtype_list);
368 printk("New Entry\n"); 411 pr_debug("New Entry\n");
369 } 412 }
370 413
371 if (ret_type) { 414 if (ret_type) {
372 printk( 415 pr_debug(
373 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n", 416 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
374 start, end, cattr_name(actual_type), 417 start, end, cattr_name(actual_type),
375 cattr_name(req_type), cattr_name(*ret_type)); 418 cattr_name(req_type), cattr_name(*ret_type));
376 } else { 419 } else {
377 printk( 420 pr_debug(
378 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n", 421 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
379 start, end, cattr_name(actual_type), 422 start, end, cattr_name(actual_type),
380 cattr_name(req_type)); 423 cattr_name(req_type));
@@ -411,11 +454,115 @@ int free_memtype(u64 start, u64 end)
411 spin_unlock(&memtype_lock); 454 spin_unlock(&memtype_lock);
412 455
413 if (err) { 456 if (err) {
414 printk(KERN_DEBUG "%s:%d freeing invalid memtype %Lx-%Lx\n", 457 printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
415 current->comm, current->pid, start, end); 458 current->comm, current->pid, start, end);
416 } 459 }
417 460
418 printk( "free_memtype request 0x%Lx-0x%Lx\n", start, end); 461 pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
419 return err; 462 return err;
420} 463}
421 464
465
466/*
467 * /dev/mem mmap interface. The memtype used for mapping varies:
468 * - Use UC for mappings with O_SYNC flag
469 * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
470 * inherit the memtype from existing mapping.
471 * - Else use UC_MINUS memtype (for backward compatibility with existing
472 * X drivers.
473 */
474pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
475 unsigned long size, pgprot_t vma_prot)
476{
477 return vma_prot;
478}
479
480int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
481 unsigned long size, pgprot_t *vma_prot)
482{
483 u64 offset = ((u64) pfn) << PAGE_SHIFT;
484 unsigned long flags = _PAGE_CACHE_UC_MINUS;
485 unsigned long ret_flags;
486 int retval;
487
488 if (file->f_flags & O_SYNC) {
489 flags = _PAGE_CACHE_UC;
490 }
491
492#ifdef CONFIG_X86_32
493 /*
494 * On the PPro and successors, the MTRRs are used to set
495 * memory types for physical addresses outside main memory,
496 * so blindly setting UC or PWT on those pages is wrong.
497 * For Pentiums and earlier, the surround logic should disable
498 * caching for the high addresses through the KEN pin, but
499 * we maintain the tradition of paranoia in this code.
500 */
501 if (!pat_wc_enabled &&
502 ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
503 test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
504 test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
505 test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
506 (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
507 flags = _PAGE_CACHE_UC;
508 }
509#endif
510
511 /*
512 * With O_SYNC, we can only take UC mapping. Fail if we cannot.
513 * Without O_SYNC, we want to get
514 * - WB for WB-able memory and no other conflicting mappings
515 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
516 * - Inherit from confliting mappings otherwise
517 */
518 if (flags != _PAGE_CACHE_UC_MINUS) {
519 retval = reserve_memtype(offset, offset + size, flags, NULL);
520 } else {
521 retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
522 }
523
524 if (retval < 0)
525 return 0;
526
527 flags = ret_flags;
528
529 if (pfn <= max_pfn_mapped &&
530 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
531 free_memtype(offset, offset + size);
532 printk(KERN_INFO
533 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
534 current->comm, current->pid,
535 cattr_name(flags),
536 offset, offset + size);
537 return 0;
538 }
539
540 *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
541 flags);
542 return 1;
543}
544
545void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
546{
547 u64 addr = (u64)pfn << PAGE_SHIFT;
548 unsigned long flags;
549 unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
550
551 reserve_memtype(addr, addr + size, want_flags, &flags);
552 if (flags != want_flags) {
553 printk(KERN_INFO
554 "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
555 current->comm, current->pid,
556 cattr_name(want_flags),
557 addr, addr + size,
558 cattr_name(flags));
559 }
560}
561
562void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
563{
564 u64 addr = (u64)pfn << PAGE_SHIFT;
565
566 free_memtype(addr, addr + size);
567}
568
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 20070b7c573d..e83623ead441 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -41,36 +41,7 @@
41 */ 41 */
42static inline int uncached_access(struct file *file, unsigned long addr) 42static inline int uncached_access(struct file *file, unsigned long addr)
43{ 43{
44#if defined(__i386__) && !defined(__arch_um__) 44#if defined(CONFIG_IA64)
45 /*
46 * On the PPro and successors, the MTRRs are used to set
47 * memory types for physical addresses outside main memory,
48 * so blindly setting PCD or PWT on those pages is wrong.
49 * For Pentiums and earlier, the surround logic should disable
50 * caching for the high addresses through the KEN pin, but
51 * we maintain the tradition of paranoia in this code.
52 */
53 if (file->f_flags & O_SYNC)
54 return 1;
55 return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
56 test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
57 test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
58 test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
59 && addr >= __pa(high_memory);
60#elif defined(__x86_64__) && !defined(__arch_um__)
61 /*
62 * This is broken because it can generate memory type aliases,
63 * which can cause cache corruptions
64 * But it is only available for root and we have to be bug-to-bug
65 * compatible with i386.
66 */
67 if (file->f_flags & O_SYNC)
68 return 1;
69 /* same behaviour as i386. PAT always set to cached and MTRRs control the
70 caching behaviour.
71 Hopefully a full PAT implementation will fix that soon. */
72 return 0;
73#elif defined(CONFIG_IA64)
74 /* 45 /*
75 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. 46 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
76 */ 47 */
@@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
108} 79}
109#endif 80#endif
110 81
82#ifdef CONFIG_NONPROMISC_DEVMEM
83static inline int range_is_allowed(unsigned long pfn, unsigned long size)
84{
85 u64 from = ((u64)pfn) << PAGE_SHIFT;
86 u64 to = from + size;
87 u64 cursor = from;
88
89 while (cursor < to) {
90 if (!devmem_is_allowed(pfn)) {
91 printk(KERN_INFO
92 "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
93 current->comm, from, to);
94 return 0;
95 }
96 cursor += PAGE_SIZE;
97 pfn++;
98 }
99 return 1;
100}
101#else
102static inline int range_is_allowed(unsigned long pfn, unsigned long size)
103{
104 return 1;
105}
106#endif
107
108void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
109{
110}
111
111/* 112/*
112 * This funcion reads the *physical* memory. The f_pos points directly to the 113 * This funcion reads the *physical* memory. The f_pos points directly to the
113 * memory location. 114 * memory location.
@@ -150,15 +151,25 @@ static ssize_t read_mem(struct file * file, char __user * buf,
150 151
151 sz = min_t(unsigned long, sz, count); 152 sz = min_t(unsigned long, sz, count);
152 153
154 if (!range_is_allowed(p >> PAGE_SHIFT, count))
155 return -EPERM;
156
153 /* 157 /*
154 * On ia64 if a page has been mapped somewhere as 158 * On ia64 if a page has been mapped somewhere as
155 * uncached, then it must also be accessed uncached 159 * uncached, then it must also be accessed uncached
156 * by the kernel or data corruption may occur 160 * by the kernel or data corruption may occur
157 */ 161 */
158 ptr = xlate_dev_mem_ptr(p); 162 ptr = xlate_dev_mem_ptr(p);
163 if (!ptr)
164 return -EFAULT;
159 165
160 if (copy_to_user(buf, ptr, sz)) 166 if (copy_to_user(buf, ptr, sz)) {
167 unxlate_dev_mem_ptr(p, ptr);
161 return -EFAULT; 168 return -EFAULT;
169 }
170
171 unxlate_dev_mem_ptr(p, ptr);
172
162 buf += sz; 173 buf += sz;
163 p += sz; 174 p += sz;
164 count -= sz; 175 count -= sz;
@@ -207,20 +218,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
207 218
208 sz = min_t(unsigned long, sz, count); 219 sz = min_t(unsigned long, sz, count);
209 220
221 if (!range_is_allowed(p >> PAGE_SHIFT, sz))
222 return -EPERM;
223
210 /* 224 /*
211 * On ia64 if a page has been mapped somewhere as 225 * On ia64 if a page has been mapped somewhere as
212 * uncached, then it must also be accessed uncached 226 * uncached, then it must also be accessed uncached
213 * by the kernel or data corruption may occur 227 * by the kernel or data corruption may occur
214 */ 228 */
215 ptr = xlate_dev_mem_ptr(p); 229 ptr = xlate_dev_mem_ptr(p);
230 if (!ptr) {
231 if (written)
232 break;
233 return -EFAULT;
234 }
216 235
217 copied = copy_from_user(ptr, buf, sz); 236 copied = copy_from_user(ptr, buf, sz);
218 if (copied) { 237 if (copied) {
219 written += sz - copied; 238 written += sz - copied;
239 unxlate_dev_mem_ptr(p, ptr);
220 if (written) 240 if (written)
221 break; 241 break;
222 return -EFAULT; 242 return -EFAULT;
223 } 243 }
244
245 unxlate_dev_mem_ptr(p, ptr);
246
224 buf += sz; 247 buf += sz;
225 p += sz; 248 p += sz;
226 count -= sz; 249 count -= sz;
@@ -231,6 +254,12 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
231 return written; 254 return written;
232} 255}
233 256
257int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
258 unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
259{
260 return 1;
261}
262
234#ifndef __HAVE_PHYS_MEM_ACCESS_PROT 263#ifndef __HAVE_PHYS_MEM_ACCESS_PROT
235static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 264static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
236 unsigned long size, pgprot_t vma_prot) 265 unsigned long size, pgprot_t vma_prot)
@@ -271,6 +300,35 @@ static inline int private_mapping_ok(struct vm_area_struct *vma)
271} 300}
272#endif 301#endif
273 302
303void __attribute__((weak))
304map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
305{
306 /* nothing. architectures can override. */
307}
308
309void __attribute__((weak))
310unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
311{
312 /* nothing. architectures can override. */
313}
314
315static void mmap_mem_open(struct vm_area_struct *vma)
316{
317 map_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
318 vma->vm_page_prot);
319}
320
321static void mmap_mem_close(struct vm_area_struct *vma)
322{
323 unmap_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
324 vma->vm_page_prot);
325}
326
327static struct vm_operations_struct mmap_mem_ops = {
328 .open = mmap_mem_open,
329 .close = mmap_mem_close
330};
331
274static int mmap_mem(struct file * file, struct vm_area_struct * vma) 332static int mmap_mem(struct file * file, struct vm_area_struct * vma)
275{ 333{
276 size_t size = vma->vm_end - vma->vm_start; 334 size_t size = vma->vm_end - vma->vm_start;
@@ -281,17 +339,28 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
281 if (!private_mapping_ok(vma)) 339 if (!private_mapping_ok(vma))
282 return -ENOSYS; 340 return -ENOSYS;
283 341
342 if (!range_is_allowed(vma->vm_pgoff, size))
343 return -EPERM;
344
345 if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
346 &vma->vm_page_prot))
347 return -EINVAL;
348
284 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, 349 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
285 size, 350 size,
286 vma->vm_page_prot); 351 vma->vm_page_prot);
287 352
353 vma->vm_ops = &mmap_mem_ops;
354
288 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ 355 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
289 if (remap_pfn_range(vma, 356 if (remap_pfn_range(vma,
290 vma->vm_start, 357 vma->vm_start,
291 vma->vm_pgoff, 358 vma->vm_pgoff,
292 size, 359 size,
293 vma->vm_page_prot)) 360 vma->vm_page_prot)) {
361 unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
294 return -EAGAIN; 362 return -EAGAIN;
363 }
295 return 0; 364 return 0;
296} 365}
297 366
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index 67dc84cd1343..76b0cc5637f8 100644
--- a/include/asm-generic/iomap.h
+++ b/include/asm-generic/iomap.h
@@ -60,6 +60,10 @@ extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long cou
60extern void __iomem *ioport_map(unsigned long port, unsigned int nr); 60extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
61extern void ioport_unmap(void __iomem *); 61extern void ioport_unmap(void __iomem *);
62 62
63#ifndef ARCH_HAS_IOREMAP_WC
64#define ioremap_wc ioremap_nocache
65#endif
66
63/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ 67/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
64struct pci_dev; 68struct pci_dev;
65extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); 69extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h
index 7b292d386713..d5b11f60dbd0 100644
--- a/include/asm-x86/io.h
+++ b/include/asm-x86/io.h
@@ -1,3 +1,6 @@
1#ifndef _ASM_X86_IO_H
2#define _ASM_X86_IO_H
3
1#define ARCH_HAS_IOREMAP_WC 4#define ARCH_HAS_IOREMAP_WC
2 5
3#ifdef CONFIG_X86_32 6#ifdef CONFIG_X86_32
@@ -5,7 +8,12 @@
5#else 8#else
6# include "io_64.h" 9# include "io_64.h"
7#endif 10#endif
11
12extern void *xlate_dev_mem_ptr(unsigned long phys);
13extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
14
8extern int ioremap_change_attr(unsigned long vaddr, unsigned long size, 15extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
9 unsigned long prot_val); 16 unsigned long prot_val);
10extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size); 17extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
11 18
19#endif /* _ASM_X86_IO_H */
diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
index 509045f5fda2..6e73467a4fb1 100644
--- a/include/asm-x86/io_32.h
+++ b/include/asm-x86/io_32.h
@@ -49,12 +49,6 @@
49#include <linux/vmalloc.h> 49#include <linux/vmalloc.h>
50 50
51/* 51/*
52 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
53 * access
54 */
55#define xlate_dev_mem_ptr(p) __va(p)
56
57/*
58 * Convert a virtual cached pointer to an uncached pointer 52 * Convert a virtual cached pointer to an uncached pointer
59 */ 53 */
60#define xlate_dev_kmem_ptr(p) p 54#define xlate_dev_kmem_ptr(p) p
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
index c2f5eef47b88..0930bedf9e4d 100644
--- a/include/asm-x86/io_64.h
+++ b/include/asm-x86/io_64.h
@@ -308,12 +308,6 @@ extern int iommu_bio_merge;
308#define BIO_VMERGE_BOUNDARY iommu_bio_merge 308#define BIO_VMERGE_BOUNDARY iommu_bio_merge
309 309
310/* 310/*
311 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
312 * access
313 */
314#define xlate_dev_mem_ptr(p) __va(p)
315
316/*
317 * Convert a virtual cached pointer to an uncached pointer 311 * Convert a virtual cached pointer to an uncached pointer
318 */ 312 */
319#define xlate_dev_kmem_ptr(p) p 313#define xlate_dev_kmem_ptr(p) p
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index 6724a4bc6b7a..b381f4a5a0bd 100644
--- a/include/asm-x86/page.h
+++ b/include/asm-x86/page.h
@@ -47,6 +47,7 @@
47#ifndef __ASSEMBLY__ 47#ifndef __ASSEMBLY__
48 48
49extern int page_is_ram(unsigned long pagenr); 49extern int page_is_ram(unsigned long pagenr);
50extern int devmem_is_allowed(unsigned long pagenr);
50 51
51extern unsigned long max_pfn_mapped; 52extern unsigned long max_pfn_mapped;
52 53
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
index b8a08bd7bd48..a496d6335d3b 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -288,6 +288,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
288 288
289#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) 289#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
290 290
291#ifndef __ASSEMBLY__
292#define __HAVE_PHYS_MEM_ACCESS_PROT
293struct file;
294pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
295 unsigned long size, pgprot_t vma_prot);
296int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
297 unsigned long size, pgprot_t *vma_prot);
298#endif
299
291#ifdef CONFIG_PARAVIRT 300#ifdef CONFIG_PARAVIRT
292#include <asm/paravirt.h> 301#include <asm/paravirt.h>
293#else /* !CONFIG_PARAVIRT */ 302#else /* !CONFIG_PARAVIRT */