]> err.no Git - linux-2.6/blobdiff - arch/x86/mm/pat.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireles...
[linux-2.6] / arch / x86 / mm / pat.c
index 9851265e4d65d40db7729bd6c899f1fd9b7753ce..277446cd30b6de81a4634061949385cb6eaede69 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/msr.h>
 #include <asm/tlbflush.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pat.h>
 #include <asm/e820.h>
@@ -386,8 +387,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
                                break;
                        }
 
-                       printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
-                              saved_ptr->start, saved_ptr->end);
+                       pr_debug(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
+                                saved_ptr->start, saved_ptr->end);
                        /* No conflict. Go ahead and add this new entry */
                        list_add(&new_entry->nd, &saved_ptr->nd);
                        new_entry = NULL;
@@ -477,14 +478,43 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
        return vma_prot;
 }
 
+#ifdef CONFIG_NONPROMISC_DEVMEM
+/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       return 1;
+}
+#else
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+       u64 from = ((u64)pfn) << PAGE_SHIFT;
+       u64 to = from + size;
+       u64 cursor = from;
+
+       while (cursor < to) {
+               if (!devmem_is_allowed(pfn)) {
+                       printk(KERN_INFO
+               "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+                               current->comm, from, to);
+                       return 0;
+               }
+               cursor += PAGE_SIZE;
+               pfn++;
+       }
+       return 1;
+}
+#endif /* CONFIG_NONPROMISC_DEVMEM */
+
 int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
                                unsigned long size, pgprot_t *vma_prot)
 {
        u64 offset = ((u64) pfn) << PAGE_SHIFT;
        unsigned long flags = _PAGE_CACHE_UC_MINUS;
-       unsigned long ret_flags;
        int retval;
 
+       if (!range_is_allowed(pfn, size))
+               return 0;
+
        if (file->f_flags & O_SYNC) {
                flags = _PAGE_CACHE_UC;
        }
@@ -518,14 +548,12 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
        if (flags != _PAGE_CACHE_UC_MINUS) {
                retval = reserve_memtype(offset, offset + size, flags, NULL);
        } else {
-               retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
+               retval = reserve_memtype(offset, offset + size, -1, &flags);
        }
 
        if (retval < 0)
                return 0;
 
-       flags = ret_flags;
-
        if (pfn <= max_pfn_mapped &&
             ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
                free_memtype(offset, offset + size);